Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从任务更新UI标签。继续_C#_.net - Fatal编程技术网

C# 从任务更新UI标签。继续

C# 从任务更新UI标签。继续,c#,.net,C#,.net,我正在处理一个Winform应用程序。方法由BackgroundWorker线程启动。我很抱歉。我刚才没有提到这一点 private void Method() { tasks[i] = Task.Factory .StartNew(() => fileProcessor.ProcessEachMachine(mdetail)) .ContinueWith(UpdateLabel, TaskContinuationOptions.OnlyOnR

我正在处理一个Winform应用程序。
方法由BackgroundWorker线程启动。我很抱歉。我刚才没有提到这一点

private void Method()
{
 tasks[i] = Task.Factory
           .StartNew(() => fileProcessor.ProcessEachMachine(mdetail))
           .ContinueWith(UpdateLabel, TaskContinuationOptions.OnlyOnRanToCompletion);
}
我有一个长时间运行的函数
ProcessEachMachine
。在延续函数
UpdateLabel
中,我想访问UIlabel并更新状态

private void UpdateLabel()
{
   progressLbl.Text = "updated";
}
但是标签没有更新。如何访问UILabel并更新其文本。?

您必须将设置为打开ContinueWith,否则它将不会在UI上下文中运行

结果应该是这样的:

.ContinueWith(UpdateLabel, null, 
    TaskContinuationOptions.OnlyOnRanToCompletion,
    TaskScheduler.FromCurrentSynchronizationContext());
看起来好像什么都没有发生,但TPL目前正在吞并您的跨线程异常。如果不打算检查每个结果或检查其异常,则可能应该使用。否则,当垃圾收集发生时,将发生异常…这可能会产生难以调试的错误

更新

根据您关于正在设置并由Backgroundworker启动的主任务的更新,我的主要问题是为什么不能使用任务启动?事实上,如果
方法中没有更多内容,那么这实际上只是双重工作,可能会让其他开发人员感到困惑。您已经异步启动了,那么为什么不在backgroundworker中执行您的工作,并使用一种将
UpdateLabel
(因为后台工作人员已经知道上下文)的方法呢

但主要问题仍然是一样的,因此,如果您觉得必须使用第三方物流,这里有一些其他解决方案:

  • 您可以
    调用
    返回到UpdateLabel方法内的主UI线程
  • 您可以将当前上下文传递给backgroundworker并使用它
  • 您可以等待原始任务返回,然后使用工作人员的oncomplete事件更新标签
  • 下面是我将如何做到这一点(所有伪代码)

    后台工作方法:

    Method() called because of Background worker
    
    private void Method()
    {
        fileProcessor.ProcessEachMachine(mdetail);
    }
    
    Wire up background worker's OnRunWorkerCompleted:
    
    if(!e.Cancelled && !e.Error)
        UpdateLabel();
    
    仅任务方法

    Call Method() from the main thread and just let the TPL do its work :)
    
    Task.Factory.StartNew(() => fileProcessor.ProcessEachMachine(mdetail))
           .ContinueWith((precedingTask)=>{if(!precedingTask.Error)UpdateLabel;}, 
               null, TaskContinuationOptions.OnlyOnRanToCompletion,
               TaskScheduler.FromCurrentSynchronizationContext());
    

    您确定
    ProcessEachMachine
    在更新标签之前完成吗?也许任务运行了很长时间,真的很长时间,这是什么保证的?我这么想是不是错了?@Sandeep不,你没有错。您只需要确保返回到UI线程。对不起。我已经纠正了这个问题。我这样做的原因是我必须连接到db,获取机器列表,然后搜索所有10台机器。如果有更好的方法,我很乐意学习。@Sandeep我提供了我的建议,基于你接受答案,我认为这已经足够解释了。但是,如果没有,我可以提供更详细的例子来说明如何做到这一点cleaner@Sandeep我已经用一些伪代码更新了我的答案,这可能有助于澄清问题?谢谢你的时间。我很感激。