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

MessageBox.showがどこにあるかを待ってから、foreachループを続行する必要があります。cleanUp(task)に到達するのに数秒かかります。//MessageBox.Show("Complete!"); セクション。

ありがとう。

4

1 に答える 1

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を維持する必要がある場合は、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);
}
于 2012-11-24T22:52:40.340 に答える