2014-03-24 102 views
0

我有一个问题,这引起了我一些头痛。 我有一个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

非常感谢你提前

回答

0

当你创建你创建了一个TaskScheduler通过新的任务使用TaskScheduler.FromCurrentSynchronizationContext();,这意味着该代码将运行UI线程,而不是另一个线程。你需要而不是编码到UI线程的代码,如果你不想它在UI线程中运行。

+0

等一下,什么'TaskScheduler'封送整个线程?!从未知道! – aevitas

+0

@aevitas它定义了应如何安排指定的任务。如果您提供了一个调度程序,用于将UI线程中运行的所有任务调度为新任务,它将在UI线程中运行。如果您提供了一个执行其他操作的调度程序,它将执行其他操作。如果您提供none,则将使用默认值,该值使用线程池。线程不封送。任务(或任何其他委托/操作)是编组的。 – Servy

+0

感谢您的解释! – aevitas