gpt4 book ai didi

c# - 从 TPL 任务向 WPF View 报告进度的适当方法是什么?

转载 作者:行者123 更新时间:2023-11-30 13:28:13 25 4
gpt4 key购买 nike

我试图以小“ block ”或页面的形式从数据库中读取大量行,并向用户报告进度;即,如果我正在加载 100 个“ block ”,则在加载每个 block 时报告进度。

我正在使用 C# 4.0 中的 TPL 从数据库中读取这些 block ,然后将完整的结果集交给另一个可以使用它的任务。我觉得与 BackgroundWorker 等相比,TPL 可以更好地控制任务取消和移交,但似乎没有内置的方式来报告任务的进度。

这是我为向 WPF 进度条报告进度而实现的解决方案,我想确保这是合适的并且没有更好的方法我应该采用。

我首先创建了一个简单的界面来表示不断变化的进度:

public interface INotifyProgressChanged
{
int Maximum { get; set; }
int Progress { get; set; }
bool IsIndeterminate { get; set; }
}

这些属性可以绑定(bind)到 WPF View 中的 ProgressBar,接口(interface)由负责启动数据加载并最终报告总体进度的支持 ViewModel 实现(此示例已简化):

public class ContactsViewModel : INotifyProgressChanged
{
private IContactRepository repository;

...

private void LoadContacts()
{
Task.Factory.StartNew(() => this.contactRepository.LoadWithProgress(this))
.ContinueWith(o => this.UseResult(o));
}
}

您会注意到我将 ViewModel 作为 INotifyProgressChanged 传递给存储库方法,这是我想确保我没有做错什么的地方。

我的想法是,为了报告进度,实际执行工作的方法(即存储库方法)需要访问 INotifyProgressChanged 接口(interface),以便报告最终更新 View 的进度。下面是存储库方法的快速浏览(在此示例中已缩短):

public class ContactRepository : IContactRepository
{
...

public IEnumberable<Contact> LoadWithProgress(INotifyProgressChanged indicator)
{
var resultSet = new List<Contact>();
var query = ... // This is a LINQ to Entities query

// Set the maximum to the number of "pages" that will be iterated
indicator.Maximum = this.GetNumberOfPages(query.Count(), this.pageSize);

for (int i = 0; i < indicator.Maximum; i++)
{
resultSet.AddRange(query.Skip(i * this.pageSize).Take(this.pageSize));
indicator.Progress += 1; // As each "chunk" is loaded, progress is updated
}

// The complete list is returned after all "chunks" are loaded
return resultSet.AsReadOnly();
}
}

这就是存储库最终通过 ViewModel 向 View 报告进度的方式。这是正确的方法吗?我是否正确使用 TPL,是否违反了任何主要规则等?此解决方案正在发挥作用,正在按预期报告进度,我只是想确保我不会为失败做好准备。

最佳答案

这样做的“规定”方式是传递 TaskScheduler来自 TaskSheduler::FromCurrentSynchronizationContext 的实例至 ContinueWith您要确保在 WPF 调度程序线程上执行。

例如:

 public void DoSomeLongRunningOperation()
{
// this is called from the WPF dispatcher thread

Task.Factory.StartNew(() =>
{
// this will execute on a thread pool thread
})
.ContinueWith(t =>
{
// this will execute back on the WPF dispatcher thread
},
TaskScheduler.FromCurrentSynchronizationContext());
}

关于c# - 从 TPL 任务向 WPF View 报告进度的适当方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6684580/

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