在迭代之前等待任务完成

.net-4.0 c# foreach sqlbulkcopy

我有一个函数从目录中读取每个文件并将其上传到数据库。我无法弄清楚如何在它返回到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的位置。到达cleanUp(任务)需要几秒钟; //MessageBox.Show("Complete“)!;部分。

谢谢。

一般承认的答案

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,你将不得不模仿async-await的作用,类似于:

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);
}



许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因
许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因