gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 21:05:37 24 4
gpt4 key购买 nike

我有一个任务,完成后应该继续另一个显示 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/

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