2013-02-13 3 views
0

я это для/следующего цикла, когда я загрузить файл, а затем процесс и загрузить его contnets в базу данных:Как выполнить две задачи одновременно?

For Each f As WinSCP.RemoteFileInfo In remotefilesinf 
     If DownloadFile(FTPSession, CacheDirPath, "/mnt/usb", f) Then 
      LoadDB(System.IO.Path.Combine(CacheDirPath, f.Name)) 
     Else 
      MsgBox("Download failed.") 
     End If 
Next 

Для того, чтобы ускорить процесс, как я могу сделать загрузку БД, а следующий файл загружается? Я не могу выполнить DBLoad до тех пор, пока загрузка каждого файла не будет завершена, и я могу выполнять только одну задачу DBLoad за разблокировку базы данных.

Я попытался использовать фоновый рабочий для задачи LoadDB, но событие RunWorkerCompleted не будет срабатывать, когда поток пользовательского интерфейса занят загрузкой, поэтому я не знаю, когда я могу сделать следующий DBload (DB не заблокирован).

Любые советы, оцененные.

ответ

2

Вот еще одна попытка, так как требование к вопросу изменились:

RunningFinished

Public Class Form1 

    Shared rnd As New Random 

    Private download_que As New Queue(Of String) 
    Private process_que As New Queue(Of String) 
    Private download_thread As Thread 
    Private process_thread As Thread 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 

    End Sub 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
     download_que.Enqueue("File 1.db") 
     download_que.Enqueue("File 2.db") 
     download_que.Enqueue("File 3.db") 
     download_que.Enqueue("File 4.db") 
     download_que.Enqueue("File 5.db") 
     download_que.Enqueue("File 6.db") 

     If download_thread Is Nothing then 
      download_thread = New Thread(AddressOf DownloadFiles) 
      download_thread.Start() 
     End If 
    End Sub 

    Private AppendTextCaller As New Action(Of TextBox, String)(AddressOf AppendText) 

    Public Sub AppendText(ByVal control As TextBox, ByVal text As String) 
     control.AppendText(text)    
    End Sub 

    Public Sub DownloadFiles() 
     Dim file As String 
     While download_que.Count > 0 
      SyncLock download_que 
       file = download_que.Dequeue() 
      End SyncLock 
      Dim path As String = Download(file) 
      SyncLock process_que 
       process_que.Enqueue(path) 
      End SyncLock 

      If process_thread Is Nothing Then 
       process_thread = New Thread(AddressOf ProcessFiles) 
       process_thread.Start() 
      End If 
     End While 
     download_thread = Nothing 
    End Sub 

    Public Sub ProcessFiles() 
     Dim path As String, ok As Boolean 
     ok = True 
     While process_que.Count > 0 And ok 
      SyncLock process_que 
       path = process_que.Dequeue() 
      End SyncLock 
      ok = LoadDB(path) 
     End While 
     process_thread = Nothing 
    End Sub 

    Public Function Download(ByVal filename As String) As String 
     Dim sw = Stopwatch.StartNew()   
     Me.Invoke(AppendTextCaller, TextBox1, filename) 
     Thread.Sleep(1500 + 500*rnd.Next(15))   
     Dim message As String = String.Format(" ({0:F1} sec)", sw.ElapsedMilliseconds/1000) 
     Me.Invoke(AppendTextCaller, TextBox1, message) 
     Me.Invoke(AppendTextCaller, TextBox1, Environment.NewLine) 
     Return IO.Path.Combine(IO.Path.GetTempPath(), filename) 
    End Function 

    Public Function LoadDB(ByVal path As String) As Boolean 
     Dim sw = Stopwatch.StartNew() 
     Dim filename = IO.Path.GetFileName(path) 
     Me.Invoke(AppendTextCaller, TextBox2, filename) 
     Thread.Sleep(800 + 500*rnd.Next(6)) 

     Dim message As String = String.Format(" ({0:F1} sec)", sw.ElapsedMilliseconds/1000) 
     Me.Invoke(AppendTextCaller, TextBox2, message) 
     Me.Invoke(AppendTextCaller, TextBox2, Environment.NewLine) 
     Return True 
    End Function 

End Class 
0

Как насчет использования двух фоновых работников? Используйте один для загрузки файлов, а другой - для вставки их в db. Если загрузка завершится, добавьте файл в список и каждый раз, когда заканчивается обновление БД, посмотрите на этот список из bgw2 ...

+0

Я пробовал что-то похожее.Таким образом, у меня был бы один рабочий стол, который загружает файл, а затем в RunWorkerComplete добавляет имя файла в список, а затем как снова запустить фонового рабочего, чтобы получить следующий файл? Аналогично, с bgw2, как мне заставить его ждать загрузки файла перед запуском задачи loadDB? – Guy

+0

Нет, я думаю, вам нужно 2 рабочих, по одному для каждого файла, который выполняет загрузку и материал последовательно. Основной поток пользовательского интерфейса может сообщать о ходе обоих файлов. – ja72

+1

Я бы не использовал событие ronworkercomplete для такого рода задач. Используйте обычный метод и просто переберитесь по всем файлам, добавив их в список. Когда закончится первый файл, запустите новый рабочий, который обрабатывает работу db. Вы можете использовать наблюдаемую коллекцию, которая запускает событие при изменении, поэтому работник знал, когда остановиться. Другой учил: используйте параллельный цикл и просто проверяйте db для блокировки, затем установите замок, некоторое время спать и повторите попытку. Это может быть что-то простое, как столбец, который содержит 1 при блокировке, 0, если нет. –

0

Вы можете запустить DBLoad на поток и установить ManualResetEvent, чтобы остановить выполнение, прежде чем наслаждаясь новой нитью DBLoad, пока другая она не закончит.

Dim locker as New ManualResetEvent(True) 

В locker действует как светофоре, останавливая выполнение и ждать, когда отмечается и происходит Повсеместно, когда в противном случае.

Заблокируйте locker в любом месте с:

locker.Reset() 

разблокированию locker в любом месте с:

locker.Set() 

Установите на место останавливая:

locker.WaitOne() 

Чтобы увидеть полные возможности увидеть MSDN.

0

Я думаю, что это то, что вы хотите:

Public Function DownLoadFile(ByVal f As String) As String 
    Trace.WriteLine("Start Downloading " & f) 
    Dim x As Integer = ProgressBar1.Value 
    Threading.Thread.Sleep(2000)   
    Me.Invoke(SetProgressCaller, x + 25) 
    Trace.WriteLine("Done Downloading " & f) 
    Return IO.Path.Combine(IO.Path.GetTempPath(), f) 
End Function 

Public Sub LoadDB(ByVal f As String) 
    Trace.WriteLine("Start Loading " & f) 
    Dim x As Integer = ProgressBar1.Value 
    Threading.Thread.Sleep(1000) 
    Me.Invoke(SetProgressCaller, x + 25) 
    Trace.WriteLine("Done Loading " & f) 
End Sub 

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
    ProgressBar1.Value = 0 
    Dim f_path_1 = DownLoadFile("File 1") 
    Dim t1 As New Threading.Thread(AddressOf LoadDB) 
    t1.Start(f_path_1) 
    ProgressBar1.Value = 50 
    Dim f_path_2 = DownLoadFile("File 2") 
    Dim t2 As New Threading.Thread(AddressOf LoadDB) 
    t2.Start(f_path_2)   
End Sub 

' Can be called using Form.Invoke() from any thread 
Private SetProgressCaller As New Action(Of Integer)(AddressOf SetProgress) 

' Set progress bar in main thread 
Public Sub SetProgress(ByVal pct As Integer) 
    ProgressBar1.Value = pct 
End Sub 

с результатами:

Start Downloading File 1 
Done Downloading File 1 
Start Downloading File 2 
Start Loading C:\Users\#####\AppData\Local\Temp\File 1 
Done Loading C:\Users\#####\AppData\Local\Temp\File 1 
Done Downloading File 2 
Start Loading C:\Users\#####\AppData\Local\Temp\File 2 
Done Loading C:\Users\#####\AppData\Local\Temp\File 2 

, который переводит

  • Загрузка файла 1 (занимает 2 сек)
  • Загрузка файла 1 в DB (занимает 1 секунду) И
  • Загрузка файла 2 (занимает 2 сек)
  • Загрузка файла 2 в БД (занимает 1 сек)
+0

ja72: Это работает, за исключением того, что количество файлов для обработки неизвестно до выполнения. Поэтому я помещаю процедуру, которая находится внутри Button1_Click в цикле (для каждого f в файлах), но затем процедуры LodDB перекрывают друг друга, в результате чего проблема блокировки базы данных проявляется. Мне нужно, чтобы процедуры LoaDB выполнялись последовательно. – Guy

+0

Возможно, вы можете обновить исходный вопрос с точными деталями, которые вы ищете. Несколько файлов, без одновременной загрузки, без одновременной загрузки в БД, допускается одновременная загрузка и доступность БД. – ja72

Смежные вопросы