C# 在一个用户界面中管理任务进度

C# 在一个用户界面中管理任务进度,c#,.net,multithreading,progress-bar,task-parallel-library,C#,.net,Multithreading,Progress Bar,Task Parallel Library,我有一个应用程序,用户可以启动任务,繁重的任务。我想在一个用户界面网格中管理这些任务的进度(每行都是一个任务,带有进度条)。用户可以通过单击按钮(使用主线程)来显示该网格。我遇到的问题是跨线程操作。我知道原因:每当任务进程发生变化时(使用thread1),算法都会尝试更新网格数据源(使用主线程)。但我不知道如何修复它 我的网格的DataSource属性设置为BindingList 我的任务定义(后台操作) 公共类后台操作 { 公共整数级数; 公共整数级数 { 获取{return progress

我有一个应用程序,用户可以启动任务,繁重的任务。我想在一个用户界面网格中管理这些任务的进度(每行都是一个任务,带有进度条)。用户可以通过单击按钮(使用主线程)来显示该网格。我遇到的问题是跨线程操作。我知道原因:每当任务进程发生变化时(使用thread1),算法都会尝试更新网格数据源(使用主线程)。但我不知道如何修复它

我的网格的DataSource属性设置为
BindingList

我的任务定义(后台操作)

公共类后台操作
{
公共整数级数;
公共整数级数
{
获取{return progression;}
设置
{
进展=价值;
不动产变更(“进展”);
}
}
公共事件事件处理程序OnRun;
公共事件事件处理程序已更改;
公共事件属性更改事件处理程序属性更改;
公开募捐
{
变量任务=新任务(()=>
{
如果(OnRun!=null)
OnRun(this,null);
});
task.Start();
}
公共进度(整数进度)
{
进展=进展;
if(OnProgressChanged!=null)
OnProgressChanged(这是新的ProgressChangedEventArgs{Progression=Progression});
}
受保护的void OnPropertyChanged(字符串名称)
{
PropertyChangedEventHandler处理程序=PropertyChanged;
if(处理程序!=null)
{
处理程序(此,新PropertyChangedEventArgs(名称));
}
}
}

您需要在UI线程上运行
OnProgressChanged
(顺便说一句,应该只调用
ProgressChanged
)。您可以在创建类时保存,然后
Post()

public class BackgroundOperation
{
    private readonly SynchronizationContext m_synchronizationContext;

    public BackgroundOperation()
    {
        m_synchronizationContext = SynchronizationContext.Current;
    }

    …

    public void ReportProgress(int progression)
    {
        Progression = progression;

        var handler = OnProgressChanged;
        if (handler != null)
            m_synchronizationContext.Post(
                _ => handler(
                    this,
                    new ProgressChangedEventArgs { Progression = progression }),
                null);
    }
}

您是否可以访问.NET4.0甚至.NET4.5+?这里您没有使用TPL,尽管我建议您这样做……您希望主线程和主线程只处理UI。这意味着您必须找到一种方法,让thread1在给定的进程上发出更改信号,并让main捕捉该信号并更新显示。一种常用的技术是拥有一个事件队列,每个线程都将产生/使用该队列。它的工作方式与它应该的一样。非常感谢你的帮助。(+1表示SynchronizationContext类)。
public class BackgroundOperation
{
    private readonly SynchronizationContext m_synchronizationContext;

    public BackgroundOperation()
    {
        m_synchronizationContext = SynchronizationContext.Current;
    }

    …

    public void ReportProgress(int progression)
    {
        Progression = progression;

        var handler = OnProgressChanged;
        if (handler != null)
            m_synchronizationContext.Post(
                _ => handler(
                    this,
                    new ProgressChangedEventArgs { Progression = progression }),
                null);
    }
}