2014-03-24 35 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