2012-11-24 46 views
1

我有一個函數,它從目錄讀取每個文件並將其上載到數據庫。 我無法工作,如何等待任務完成它可以追溯到foreach循環之前,因爲它似乎做直線距離,那裏的任務需要幾秒鐘:在迭代之前等待任務完成

foreach (string file in Directory.EnumerateFiles(folderPath, "*.xml")) 
{ 
    //load file 
    currentReader = new XmlDataReader(transferInstructions, file); 

    currentReader.RowsUploaded += new EventHandler<RowsUploadedEventArgs>(currentReader_RowsUploaded); 
    currentReader.TableUploaded += new EventHandler<TableUploadedEventArgs>(currentReader_TableUploaded); 
    currentTask = new Task(() => currentReader.executeBulkCopy(initialConnString, workingDatabase)); 
    currentTask.ContinueWith(task => 
    { 
     cleanUp(task); 
     //MessageBox.Show("Complete!"); 
    }); 
    currentTask.Start(); 
    writeResult("Started the transfer process."); 
    cmdDataTransfer.Text = "CANCEL TRANSFER"; 
    cmdDataTransfer.ForeColor = Color.DarkRed; 
    transferAction =() => cancelCurrentReader(); 
} 

我需要在繼續執行foreach循環之前,請等待MessageBox.show的位置。 清潔(任務)需要幾秒鐘的時間。 //MessageBox.Show("Complete!「); 部分。

謝謝。

回答

4

C#5/.NET 4.5中的async-awqait模式與此完美匹配。我看你已經標記這是.NET4,但如果你能使用Async Targeting Pack,有這樣做的一個非常優雅的方式:

void Main() 
{ 
    foreach (string file in Directory.EnumerateFiles(folderPath, "*.xml")) 
    { 
     currentReader = new XmlDataReader(transferInstructions, file); //load file 
     currentReader.RowsUploaded += new EventHandler<RowsUploadedEventArgs>(currentReader_RowsUploaded); 
     currentReader.TableUploaded += new EventHandler<TableUploadedEventArgs>(currentReader_TableUploaded); 

     var task = Task.Factory.StartNew(() => currentReader.executeBulkCopy(initialConnString, workingDatabase)); 
     await task; 

     cleanUp(task); 
     MessageBox.Show("Complete!"); 
     writeResult("Started the transfer process."); 
     cmdDataTransfer.Text = "CANCEL TRANSFER"; 
     cmdDataTransfer.ForeColor = Color.DarkRed; 
     transferAction =() => cancelCurrentReader(); 
    } 
} 

如果你必須保持VS2010,你將不得不效仿什麼異步等待,沿線的東西:

void MyForm() 
{ 
    _syncContext = SynchronizationContext.Current; 
    Execute(Directory.EnumerateFiles(folderPath, "*.xml").GetEnumerator()); 
} 

void Execute(IEnumerator<string> files) 
{ 
    if (!files.MoveNext()) 
    { 
     files.Dispose(); 
     return; 
    } 
    Task.Factory.StartNew(() => Execute(files.Current)).ContinueWith(() => Execute(files)); 
} 

public void Execute(string file) 
{ 
    currentReader = new XmlDataReader(transferInstructions, file); //load file 
    currentReader.RowsUploaded += new EventHandler<RowsUploadedEventArgs>(currentReader_RowsUploaded); 
    currentReader.TableUploaded += new EventHandler<TableUploadedEventArgs>(currentReader_TableUploaded); 
    () => currentReader.executeBulkCopy(initialConnString, workingDatabase); 
    cleanUp(task); 
    _syncContext.Send(updateGUI); 
    transferAction =() => cancelCurrentReader(); 
} 
public void updateGUI() 
{ 
    MessageBox.Show("Complete!"); 
    writeResult("Started the transfer process."); 
    cmdDataTransfer.Text = "CANCEL TRANSFER"; 
    cmdDataTransfer.ForeColor = Color.DarkRed; 
} 

編輯現在我想到它也有一個更簡單的方法。您可以讓整個循環運行在它自己的任務中(委派到GUI工作的同步上下文)。使用上面的代碼的約定:

Task.Factory.StartNew(() => 
{ 
    foreach (var file in Directory.EnumerateFiles(folderPath, "*.xml")) 
     Execute(file); 
} 
+0

嗨,感謝您,這看起來不錯,但我寧願保持這個項目.net 4.0和VS2010。 –

+0

@Dan - 使用異步定位包*保持您的項目.NET4 * - 這就是整個想法。你不得不使用VS2012(或使用2010年的AsyncCTP,但不再支持) –

+0

嗨,我不能得到.net4的建議工作,所以我強迫自己使用VS2012和.net4.5,它的工作原理一個治療的感謝。 –