c# – 为什么Window.ShowDialog在TaskScheduler任务中没有阻塞?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 为什么Window.ShowDialog在TaskScheduler任务中没有阻塞?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3047字,纯文字阅读大概需要5分钟。
内容图文
![c# – 为什么Window.ShowDialog在TaskScheduler任务中没有阻塞?](/upload/InfoBanner/zyjiaocheng/817/54c6d4e5d9524e6b84896d6ce8bf7b76.jpg)
我正在使用自定义TaskScheduler来串行执行任务队列.任务应该显示一个窗口,然后阻止,直到窗口自行关闭.不幸的是,调用Window.ShowDialog()似乎没有阻塞,因此任务完成,窗口永远不会显示.
如果我在调用ShowDialog之后放置一个断点,我可以看到表单已经打开但是在正常执行下,Task似乎很快就会结束你无法看到它.
我的TaskScheduler实现取自上一个问题:
public sealed class StaTaskScheduler : TaskScheduler, IDisposable
{
private readonly List<Thread> threads;
private BlockingCollection<Task> tasks;
public override int MaximumConcurrencyLevel
{
get { return threads.Count; }
}
public StaTaskScheduler(int concurrencyLevel)
{
if (concurrencyLevel < 1) throw new ArgumentOutOfRangeException("concurrencyLevel");
this.tasks = new BlockingCollection<Task>();
this.threads = Enumerable.Range(0, concurrencyLevel).Select(i =>
{
var thread = new Thread(() =>
{
foreach (var t in this.tasks.GetConsumingEnumerable())
{
this.TryExecuteTask(t);
}
});
thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.STA);
return thread;
}).ToList();
this.threads.ForEach(t => t.Start());
}
protected override void QueueTask(Task task)
{
tasks.Add(task);
}
protected override IEnumerable<Task> GetScheduledTasks()
{
return tasks.ToArray();
}
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
return Thread.CurrentThread.GetApartmentState() == ApartmentState.STA && TryExecuteTask(task);
}
public void Dispose()
{
if (tasks != null)
{
tasks.CompleteAdding();
foreach (var thread in threads) thread.Join();
tasks.Dispose();
tasks = null;
}
}
}
我的申请代码:
private StaTaskScheduler taskScheduler;
…
this.taskScheduler = new StaTaskScheduler(1);
Task.Factory.StartNew(() =>
{
WarningWindow window = new WarningWindow(
ProcessControl.Properties.Settings.Default.WarningHeader,
ProcessControl.Properties.Settings.Default.WarningMessage,
processName,
ProcessControl.Properties.Settings.Default.WarningFooter,
ProcessControl.Properties.Settings.Default.WarningTimeout * 1000);
window.ShowDialog();
}, CancellationToken.None, TaskCreationOptions.None, this.taskScheduler);
解决方法:
没有什么明显错的.除了缺少的内容之外,您没有做任何事情来确保报告在任务中引发的异常.你编写它的方式,永远不会报告这样的异常,你只会看到代码无法运行.就像一个刚刚消失的对话框.你需要写这样的东西:
Task.Factory.StartNew(() => {
// Your code here
//...
}, CancellationToken.None, TaskCreationOptions.None, taskScheduler)
.ContinueWith((t) => {
MessageBox.Show(t.Exception.ToString());
}, TaskContinuationOptions.OnlyOnFaulted);
有很好的赔率你现在会看到报告的InvalidOperationException.使用Debug Exceptions进一步诊断它,勾选CLR异常的Thrown复选框.
请注意,此任务调度程序不会神奇地使您的代码线程安全或适合运行另一个UI线程.它不是为此而设计的,它只应用于保持单线程COM组件的快乐.您必须遵守在另一个线程上运行UI的有时严苛的后果.换句话说,请勿触摸主线程上的UI属性.并且对话框根本不像对话框,因为它没有所有者.因此,它随机消失在另一个窗口后面,或者被用户意外关闭,因为他点击了,并且从未计入过无窗口出现的窗口.
最后但并非最不重要的是SystemEvents类造成的长期痛苦.哪个需要猜测哪个线程是UI线程,它将选择第一个STA线程.如果这是你的对话框,那么你将很难在以后诊断线程问题.
不要这样做.
内容总结
以上是互联网集市为您收集整理的c# – 为什么Window.ShowDialog在TaskScheduler任务中没有阻塞?全部内容,希望文章能够帮你解决c# – 为什么Window.ShowDialog在TaskScheduler任务中没有阻塞?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。