1

Funcと呼ばれるバックグラウンドスレッドで渡されたスレッドを呼び出すメソッドがありますTaskSpinDataGridViewこれは、 (DGV)でクリックされたサイトに基づいて、一度に1つの方法を実行し、一度に1つだけ実行できる必要があります。そこで、サイト(DGVのボタンセル)をクリックすると、そのサイトでメソッドが実行されます。今はたくさんのサイトがあり、何百回もクリックして待つのではなく、DGVに含まれるすべてのサイトをバッチ処理したいと思っています。これらを実行するためにストレートループを使用することはできません。

foreach (DataGridViewRow row in this.DGV)
    TaskSpin(SomeMethod, SomeParameterArray);

これはほとんどすぐに呼び出し元に戻り、共有ファイルを使用するため、次のサイトの実行を開始します。したがって、サイトを1つずつ実行するためにキューに入れる方法が必要です。を使用することにしましたConncurrentCollection - BlockingCollectionが、行き詰まりました。いくつかのボタンクリックイベントで私は持っています

BlockingCollection<Action<object[]>> taskQueue = 
    new BlockingCollection<Action<object[]>>();
List<object[]> paramQueue = new List<object[]>();
foreach (DataGridViewRow row in this.DataGridViewDrg.Rows) 
{
    paramQueue.Add(DrgDataRowInfo(row.Index));
    Action<object[]> action = new Action<object[]>(AsyncMethod);
    taskQueue.Add(action);
}
int i = 0;
foreach (Action<object[]> action in taskQueue.GetConsumingEnumerable())
    action(paramQueue[i]);

ここでAsyncMethod、TPLを使用してバックグラウンドスレッドでsetメソッドを起動しました。

private void AsyncMethod(object[] siteInfo)
{
    TaskSpin(BuildDataForSite, siteInfo);
}

私の期待は、これがAction<object[]>次々に実行されることです。しかし、これは私のアプリケーションをフリーズさせているだけです。私はここで何が間違っているのですか?

御時間ありがとうございます。

*編集。TaskSpin *

public TaskSpin(Func asyncMethod, object[] methodParameters)
{
    ...
    asyncTask = Task.Factory.StartNew<bool>(() => 
        asyncMethod(uiScheduler, methodParameters));

    asyncTask.ContinueWith(task =>
    {
        ...
        // Finish the processing update UI etc.
        ...
    }
    ...
}
4

2 に答える 2

3

コード

foreach (Action<object[]> action in taskQueue.GetConsumingEnumerable())
    action(paramQueue[i]);

UIスレッドで実行されているため、ブロックが発生します。

あなたの要件は、UI以外のスレッドで一度に1つずつリストを処理したいということのようです。現在のコードと最小限の変更でこれを実現するには、たとえばforeachを実行する単一のタスクを作成するなどして、上記のforeachを別のスレッドに移動できます。

Task.Factory.StartNew(() =>
{
    foreach (Action<object[]> action in taskQueue.GetConsumingEnumerable())
        action(paramQueue[i]);
});
于 2012-08-01T17:10:52.763 に答える
0

私は遅れていますが

私の解決策は、Task.Runの代わりに使用することですTask.Factory.StartNew

Task.Run(() =>
{
    foreach (Action<object[]> action in taskQueue.GetConsumingEnumerable())
        action(paramQueue[i]);
});

私はこの記事に基づいてこの回答を投稿しています

私も使用してTask.Factory.StartNewいましたが、UIスレッドで実行され、アプリがハングすることがありました。Task.Run私の問題を解決しました。

于 2019-09-27T11:49:29.357 に答える