2016-04-30 9 views
0

コピーアプリの現実的な「残り時間」アプリを正しく見積もっている問題があります。私はFilestreamをコピーに使用しています。コピーされるファイルは1MB以上から4GBまでです。私はすべての上にFILECOPYの現在位置を計算するためにここにpercentageTotalを使用しています:ファイルコピーの残り時間を正しく計算する問題

'Loop through each file in the SourceDir 
      For Each ChildFile In SourceDir.GetFiles() 

       If (worker.CancellationPending = True) Then 
        e.Cancel = True 
       End If 

       'Calculate data being moved for eta to completion 
       Dim filetotalbytes As Double = ChildFile.Length 
       filetotalsofarcopied = filetotalbytes + filetotalsofarcopied 


       'Display file being copied 
       SetLabelText_ThreadSafe(Me.lblStatus, "Copying: " & line & "\" & ChildFile.Name & "") 

       'Do the copy 
       ChildFile.CopyTo(Path.Combine(DestDir.FullName, ChildFile.Name), True) 

       'Contruct Destination and Source Strings 
       deststring = DestDir.ToString & "\" & ChildFile.Name 
       Dim sourcedirstring As String 
       sourcedirstring = SourceDir.ToString & "\" & ChildFile.Name 

     Dim CopyStream As New FileStream(sourcedirstring, FileMode.Open, FileAccess.Read) 
     Dim NewStream As New FileStream(deststring, FileMode.Append) 

     Dim Buffer(4096) As Byte 
     Dim BytesRead As Integer 
     Dim len As Long = CopyStream.Length - 1 

     While CopyStream.Position < len 


      BytesRead = CopyStream.Read(Buffer, 0, Buffer.Length) 
      NewStream.Write(Buffer, 0, BytesRead) 

      percentageTotal = ((NewStream.Length + filetotalsofarcopied)/Overallsize * 100) 
      percentageTotal = Decimal.Round(percentageTotal) 

      ' SetLabelText_ThreadSafe(Me.lblTotalProgress, "" & percentageTotal & "%") 

     End While 

     CopyStream.Dispose() 
     NewStream.Dispose() 

私は私が期待するようpercentageTotalの値は、多くの場合、むしろライナーファッションの増加よりもジャンプすることを見つけます。私がどこに間違っているのか誰にでも見える?

さらに、私はsecondsremaining値のロジックを完成させることができません。現在のところ、最初に実行されてから急速に減少する前のコピーを表示していますが、残りの時間は明らかではありません。

'Start process snippit 
'Start Button Click config - starts the backgroundworker 
Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 

    'Set start value - label22 is hidden on form1 
    Label22.Text = "0" 

    'Start timers 
    Timer3.Start() 
    Timer4.Start() 


    'Start background worker 
    BackgroundWorker1.WorkerSupportsCancellation = True 
    BackgroundWorker1.WorkerReportsProgress = True 
    BackgroundWorker1.RunWorkerAsync() 

End Sub 

UPDATED!そして、残り時間を計算し、フォームの最後にTimer.Tickコード:

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick 
    byteslastsecond = filetotalsofarcopied 
End Sub 


'Every tick of Timer4 calculates the time needed to complete the copy. 
    Private Sub Timer4_Tick(sender As Object, e As EventArgs) Handles Timer4.Tick 
    Dim time As Long = Label22.Text 
    If percentageTotal = 0 Then 
     SetLabelText_ThreadSafe(Me.lblEstTimeLeft, "Estimated Time Left (All Files): Estimating...") 
    Else 
     Dim secondsRemaining As Double = (Overallsize - filetotalsofarcopied)/(filetotalsofarcopied - byteslastsecond) 
     Dim ts As TimeSpan = TimeSpan.FromSeconds(secondsRemaining) 

は、誰もがより現実的であることを残りの時間のための私のロジックを修正することはできますか?

+2

Option Strict – Plutonix

+0

** First **を有効にすることから始めますが、 'filetotalsofarcopied'変数は更新されていないようです。これはあなたのパーセンテージを "不安定にする"問題かもしれません。削除するだけでうまくいくはずです。 ** ---第2に、 'Windows.Forms。Timer'は既にUIスレッド上で動作しているため、別のタイマーを使用しない限り、 'SetLabelText_ThreadSafe()'メソッドは必要ありません。 ** ---最後に**、コピーの残り時間は次のように計算することができます: '秒=((合計ファイルサイズ - コピーバイト数)/(コピーしたバイト数 - 最後にコピーしたバイト数))'。 –

+0

@VisualVincentが返信してくれてありがとう - 'filetotalsofarcopied'が更新されている場所を含めるようにコードを更新しました。どのように '秒を左に= ...'コードで記述しますか? '最後にコピーされたバイト数'を表現する方法がわかりません 'double =(オーバーオール化 - ファイル総和なし)/(tiletotalsofarcopied - ???)' – Adam

答えて

1

コードに問題があると、ファイル全体がまだコピーされていなくても、ファイルサイズ全体でfiletotalsofarcopiedをインクリメントすることになります。データのブロックをコピーするときに、それを増やす必要があります。

ので、この削除:

'Calculate data being moved for eta to completion 
Dim filetotalbytes As Double = ChildFile.Length 
filetotalsofarcopied = filetotalbytes + filetotalsofarcopied 

をし、代わりにあなたのWhile -loopにそれを置く:

BytesRead = CopyStream.Read(Buffer, 0, Buffer.Length) 
NewStream.Write(Buffer, 0, BytesRead) 

filetotalsofarcopied += BytesRead 

percentageTotal = ((NewStream.Length + filetotalsofarcopied)/Overallsize * 100) 
percentageTotal = Decimal.Round(percentageTotal) 

これは正しく時間推定作業、およびパーセント表示の両方を行う必要があります。


ます。また、これを削除する必要があります。

'Do the copy 
ChildFile.CopyTo(Path.Combine(DestDir.FullName, ChildFile.Name), True) 

あなたは二回、ファイルをコピーすることで、時間とリソースの両方を無駄にしているので。


EDIT:

は実は、私は何かが欠けていることでミスを犯しました。

これ:

percentageTotal = ((NewStream.Length + filetotalsofarcopied)/Overallsize * 100) 

このようになります。書き込まれたバイトの電流量が既にBytesRead変数介しfiletotalsofarcopiedに追加されるので

percentageTotal = (filetotalsofarcopied/Overallsize * 100) 

+0

@visualvincet変更を反映するようにコードを更新しました。あなたの助けをもう一度ありがとう! – Adam

+0

@Adam:問題ありません、私は助けてうれしいです!しかし、「より良い」と言えば、それはあなたが望むように、あるいは以前よりもうまく機能するが、あなたが望むように完全には機能しないということを意味するのだろうか? –

+0

@visialvincentこれは以前よりも優れていますが、%完了と残りの時間との間の残りの相関関係はまだゼロではありません。特に大量の小さなファイル(約8MB)の場合は特にそうです。私はそれを「Windowsの時間」に置きます。どのようにしてより良いことができますか?あなたはすでにあまりにも多くのことを尋ねることはできませんでした。 – Adam

関連する問題