gpt4 book ai didi

c# - FromCurrentSynchronizationContext,我错过了什么吗?

转载 作者:行者123 更新时间:2023-12-02 01:16:34 26 4
gpt4 key购买 nike

我目前正在处理一个从大型二进制文件读取的应用程序,该文件包含数千个文件,每个文件都由应用程序中的其他类处理。此类返回一个对象或 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 数据流的新手,所以我希望有人能分享一些关于为什么在第二个代码片段中有效而在第一个片段中无效的原因。

亲切的问候,马丁

最佳答案

您的 UI 被阻止的原因是因为您正在使用 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 线程上执行任何长时间运行的操作(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);

关于c# - FromCurrentSynchronizationContext,我错过了什么吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10673402/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com