c# - 在 UI 线程中任务完成时显示表单

标签 c# .net scheduled-tasks task-parallel-library continuations

我有一个任务,完成后应该继续执行另一个显示 winform 的任务(winform 先前在 UI 线程上初始化,因此它确实有一个句柄)。

    private static Task RunningTask
    {
        get;
        set;
    }
    public static UpdaterTool.Forms.UpdateResult UpdateResultForm;

    private void DoWork()
    {
        UpdateResultForm = new Forms.UpdateResult(); 
        //the next line forces the creation of the handle - 
        //otherwise InvokeRequired will later on return false.
        var hackHandle = UpdateResultForm.Handle; 

        var ctx = TaskScheduler.FromCurrentSynchronizationContext();

        RunningTask = Task.Factory.StartNew(() => DownloadAndInstallFiles(), CancelTokenSource.Token)
            .ContinueWith(_ => WorkComplete(), CancelTokenSource.Token, TaskContinuationOptions.NotOnFaulted, ctx);
    }

    private void WorkComplete()
    {
       ShowResultForm();
    }

    private void ShowResultForm()
    {
        if (UpdateResultForm.InvokeRequired)
        {
            try
            {
                UpdateResultForm.Invoke(new MethodInvoker(ShowResultForm));
            }
            catch { }
            return;
         }
         UpdateResultForm.Show();

     }

问题是,无论我使用ContinueWith()的哪种重载组合,UpdateResultForm要么根本不显示(意味着不会发生延续,工作线程卡在“正在运行”),要么当它是,它会挂起 UI,就像它期望工作线程完成一样。我不明白为什么当我尝试使用 FromCurrentSynchronizationContext() 在 UI 线程上显示它时会发生这种情况。

根据我的理解,在 DoWork 方法中,我从 UI 线程开始(这就是我在那里初始化表单的原因)。当代码进入Task.Factory.StartNew时,它会切换到工作线程。完成后,它会继续执行 WorkComplete,它仅在 UI 线程上显示先前初始化的表单。

我错过了什么?谢谢,

最佳答案

使用 InvokeRequired 是一种强大的反模式。不知道方法在哪个线程上运行的情况并不常见。这里的情况也是如此,您已经使用了 TaskScheduler.FromCurrentSynchronizationContext(),因此您知道该任务在 UI 线程上运行。没有必要再次检查。这也消除了提前创建表单句柄的需要。

您遇到的此类问题可能是由从工作线程运行 DoWork() 引起的。也许您也从任务中调用了它。这使得 FromCurrentSynchronizationContext() 返回错误的上下文。并将在不泵送消息循环的线程上显示表单,它将像门钉一样死掉。或者通过阻塞 UI 线程,等待任务完成。这总是会导致死锁,除非 UI 线程空闲并且可以执行 ShowResultForm() 方法,否则任务无法完成。

关于c# - 在 UI 线程中任务完成时显示表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11591197/

相关文章:

c# - 跟踪代码随时间的变化

c# - 嵌套 UserControl 事件在 MVVM/WPF 场景中不适用于 EventTrigger/InvokeCommandAction

c# - 实现 IEqualityComparer 时,GetHashCode 是否应该检查 null?

c# - 如何使 C# Create.Delegate 支持继承?

java - 可以使用 cronj4 设置开始日期吗?

c# - 为什么在这里使用 yield 返回?

c# - .Net 中 protected 内部是什么意思

java - 如何确保 MultiResourceItemReader 在每次执行作业时刷新资源

java - Android 在特定时间后启动/停止重复线程

c# - ItemsControl 中的 ScrollViewer - ScrollBar 未显示但有效