我有一个问题,这引起了我一些头痛。 我有一个Winform应用程序,它显示一个非常简单的对话框,只有一个按钮的用户:“扫描”。按钮的点击处理程序,您怎么能想象,使用WIA COM对象开始扫描操作。 就代码而言,当按钮按下时,它会创建一个新的异步Task,它调用Item类的Transfer方法。 问题是UI线程自行冻结,直到扫描结束,尽管扫描对象正在另一个线程上工作。 MSDN上的文档说:C#WIA传输方法锁UI线程
“传输本质上是ShowTransfer的一个版本,它不显示UI或允许用户取消传输。”
所以我认为,在句子“不显示UI”的情况下,这意味着对话将会被创建,但它仍然是不可见的。然后这个对话框将自己挂接到主线程(UI)并导致冻结(与模态对话框一样)。实际上,当我尝试使用ShowTransfer
方法时,它已打开其对话框,但应用程序的UI线程未遭受冻结。
这是我的代码:
var progress = new Progress<string>(s => labelControl1.Text = s);
var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
var cancelSrc = new CancellationTokenSource();
await Task.Factory.StartNew(() => {
var facade = new ScanFacade();
facade.Scan(progress);
}, cancelSrc.Token, TaskCreationOptions.LongRunning, scheduler);
而且这是一个讲求传输扫描方法的一部分:
var imageFile = (ImageFile) _item.Transfer(FormatID.wiaFormatTIFF);
var buffer = (byte[])imageFile.FileData.get_BinaryData();
return Image.FromStream(new MemoryStream(buffer)) as Bitmap;
是我的假设是否正确? 如何在不使用WIA对话框的情况下避免此行为?
注:线程都在STA
非常感谢你提前
等一下,什么'TaskScheduler'封送整个线程?!从未知道! – aevitas
@aevitas它定义了应如何安排指定的任务。如果您提供了一个调度程序,用于将UI线程中运行的所有任务调度为新任务,它将在UI线程中运行。如果您提供了一个执行其他操作的调度程序,它将执行其他操作。如果您提供none,则将使用默认值,该值使用线程池。线程不封送。任务(或任何其他委托/操作)是编组的。 – Servy
感谢您的解释! – aevitas