2016-11-11 11 views
0

私は、トップレベルのタスクが終了したときに同時に実行する必要がある2つのタスクを持っています。C#添付されたタスクは決して実行されません

もう少しバックグラウンドでは、チャイルドタスクは長いクエリを実行しており、外部タスクは何かが起きていることをユーザーが知るように(invokeを介して)UIにカウンタを表示しています。子タスクが完了すると、その結果でUIが更新され、その時点でカウンタ(親タスク)は不要になります。ただし、タスクが開始されたときに親タスクのみが開始されると、子タスクは決して実行されません。ちなみに私は複数のクエリ/カウンタを同時に実行できる必要があるため、このためにBackgroundWorkerを使用していません。

タスクがDataGridViewの中にクリックイベントで開始されています

この構文は、次の資料から取られ
private void hostMgmtDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e) 
{ 
    var parent = Task.Factory.StartNew(() => 
    { 
     showTimer(e.ColumnIndex, e.RowIndex, 0); 
     var child = Task.Factory.StartNew(() => 
     { 
      winUpdate(hostMgmtDataGridView.Rows[e.RowIndex].Cells[1].Value.ToString(), e.ColumnIndex, e.RowIndex); 
     },TaskCreationOptions.AttachedToParent); 
    }); 
} 

https://msdn.microsoft.com/en-us/library/dd997417(v=vs.100).aspx

私は)(parent.Waitを追加した場合、上記の記事で説明したように、UIスレッド全体がロックされますが、これは望ましい結果ではありません。

何か提案がありがとうございます。

編集:私はparent.Wait(に残せばUIスレッドがロックアップ)もう一度

var parent = Task.Factory.StartNew(() => 
{ 
    debugLabel1.Invoke(new Action(() => debugLabel1.Text = "parent starting")); 

    var child = Task.Factory.StartNew(() => 
    { 
     debugLabel2.Invoke(new Action(() => debugLabel2.Text = "child starting")); 
     Thread.SpinWait(5000000); 
     debugLabel2.Invoke(new Action(() => debugLabel2.Text = "child stopped")); 
    },TaskCreationOptions.AttachedToParent); 
}); 
parent.Wait(); 
debugLabel1.Text = "parent stopped"; 

私は記事(私のフォームのために少しの適応)からのサンプルコードを使用してみました。私がWaitステートメントを取り出した場合、「親が停止しました」というメッセージは表示されませんが、「子が停止しました」が表示されます。

多くの人が「ContinueWith」の使用を提案していますが、同時に実行するには両方のタスクが必要です。Continuationはタスクを順番に実行します。

答えて

0

あなたのロックはUI変更の実装によって引き起こされる可能性があります。 私はこれを使って同じことを達成することができます。

var context = TaskScheduler.FromCurrentSynchronizationContext(); 
      var parent = Task.Factory.StartNew(() => { 

      Task.Delay(40000); 
       MessageBox.Show("From Parent"); 
      var child = Task.Factory.StartNew(() =>{ 
       MessageBox.Show("From Child"); 
       Task.Delay(30000); 
       Text = "Title change from Child"; 
      }); 
      }, CancellationToken.None, TaskCreationOptions.AttachedToParent, context); 

編集:あなたはフレームワーク4.5を使用している場合は、私が代わりにTask.Factory.StartNewのTask.Runを使用することをお勧めし、

また次の文に関しては、以下のEVKのコメントを見るくださいhttps://blogs.msdn.microsoft.com/pfxteam/2011/10/24/task-run-vs-task-factory-startnew/詳細については

+0

Task.RunがStartNewをDenyChildAttachオプションで呼び出すため、この特定のケースではTask.Runに関するアドバイスが適切ではないことに注意してください。 – Evk

+0

ありがとうございました。私は今日何か新しいことを学んだ:-) – Sammy

+0

あなたのコードを無駄にしようとしました - それはUIスレッドをロックします:( CancellationToken.Noneとコンテキストを取り出すと、UIスレッドはロックされませんが、 これらの問題の原因となっているイベントハンドラからこれらのタスクを開始することができますか? –

関連する問題