FromCurrentSynchronizationContext、私は何かがありませんか?
-
12-12-2019 - |
質問
現在の機能数千個のファイルを保持する大きなバイナリファイルから読み取るアプリケーションの機能。すべてのファイルは、アプリケーション内の他のクラスによって処理されています。このクラスはオブジェクトまたはnullを返します。私は主な形の進歩を見せたいですが、何らかの理由で私はそれを中心に私の頭を届けることができない。
int TotalFound = 0;
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext;
BufferBlock<file> buffer = new BufferBlock<file>();
DataflowBlockOptions options = new DataflowBlockOptions(){ TaskScheduler = uiScheduler, };
var producer = new ActionBlock<someObject>(largeFile=>{
var file = GetFileFromLargeFile(largeFile);
if(file !=null){
TotalFound++;
buffer.post(file);
lblProgress.Text = String.Format("{0}", TotalFound);
}
}, options);
.
上記のコードは私の形式を凍結します、「TaskScheduler.FromCurrentSynchronizationContext」を使用しています。フォームアップデートの下のコードを使用すると元気
DataflowBlockOptions options = new DataflowBlockOptions(){ TaskScheduler = uiScheduler, };
var producer = new ActionBlock<someObject>(largeFile=>{
var file = GetFileFromLargeFile(largeFile);
if(file !=null){
Task.Factory.StartNew(() => {
TotalFound++;
buffer.Post(file);
}).ContinueWith(uiTask => {
lblProgress.Text = String.Format("{0}", TotalFound);
},CancellationToken.None, TaskContinuationOptions.None, uiScheduler);
}
});
.
このTPLデータフローの全体に新品であるので、誰かが2番目のコードスニペットで、それが機能しないのか、そしてそれがそうでない最初のスニペットで何らかの光を共有できることを願っています。
親切 Martijn
解決
あなたのUIがブロックされている理由は、 bechase FromCurrentSynchronizationContext
を使用しています。コードはUIスレッド上で実行されます。これは、長い実行アクションを実行している場合はフリーズすることを意味します(ほとんどの場合、GetFileFromLargeFile()
)。
その一方で、UIスレッド上のlblProgress.Text
を実行する必要があります。
このコードでlblProgress.Text
を直接設定する必要がありません、それは私への密接なカップリングのように見えます。しかし、あなたがそれをしたいのなら、私はあなたがUIスレッド上のその行だけを実行するべきだと思います:
.
var producer = new ActionBlock<someObject>(async largeFile =>
{
var file = GetFileFromLargeFile(largeFile);
if (file != null)
{
TotalFound++;
await buffer.SendAsync(file);
await Task.Factory.StartNew(
() => lblProgress.Text = String.Format("{0}", TotalFound),
CancellationToken.None, TaskCreationOptions.None, uiScheduler);
}
});
しかし、より良いソリューションでさえも、GetFileFromLargeFile()
を非同期化し、UIスレッド上で長時間実行されていない場合(http://msdn.microsoft.com/jaus-us)。 /library/system.threading.tasks.task.configureAwait%28v=vs.110%29.aspx "rel=" nofollow "> ConfigureAwait(false)
はそれを使うことができます)。その結果、ActionBlock
のコードは、UIを凍結せずにUIスレッド上で実行できます。
.var producer = new ActionBlock<someObject>(async largeFile =>
{
var file = await GetFileFromLargeFile(largeFile);
if (file != null)
{
TotalFound++;
await buffer.SendAsync(file);
lblProgress.Text = String.Format("{0}", TotalFound)
}
}, options);