2016-06-13 25 views
0

我有一種方法利用SendKeys.Send,等待幾秒鐘,使用System.Threading.Thread.Sleep,然後運行另一種方法來檢查像素的顏色以查看它是否已更改。然後該方法再次運行,因爲它是遞歸調用的。遞歸方法在UI上施加應變

此方法需要能夠在停止前運行數千次。運行時,Winform的用戶界面似乎停止響應。

我試圖實現一個後臺工作來消除UI的壓力。我搬到了遞歸方法的代碼移交給Do_Work事件,並與RunWorkerAsync叫,但它墜毀,報告如下:

An exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll but was not handled in user code 

Additional information: SendKeys cannot run inside this application because the application is not handling Windows messages. 

什麼是從UI移動碼遠的最佳方式?我對背景工作人員不是很熟悉,所以我可能做錯了。

+0

你可以使用後臺工作者,只需使用'Invoke(new Action (SendKeys.Send),keys)'在UI線程上分派調用。 – Lou

+1

BGW不會幫你在這裏。 BGW存在移動長時間運行,** CPU綁定**,*非UI *任務到另一個線程。你有一個長期的* IO綁定*,* UI *操作在你的手中。 – Servy

回答

0

聽起來像async的情況。嘗試用Task.Delay()替換Thread.Sleep()

async void Button_Click(object sender, RoutedEventArgs e) 
{ 
    await SendMyKeysAsync(); 
} 

async Task SendMyKeysAsync() 
{ 
    while (thePixelIsStillRed) 
    { 
     SendKeys.Send("whatever"); 
     await Task.Delay(TimeSpan.FromSeconds(1)); 
    } 
} 

這種方法留下自由地繼續在延遲時間內抽消息UI線程,沒有任何產卵額外的線程。

+0

沒有任何理由使此方法遞歸。你只是顯着增加資源消耗,並沒有真正的理由使用非慣用模式。 – Servy

+1

@Servy OP聲明方法以這種方式遞歸調用自己;方法就是堅持這一點。不是說這是個好主意,儘管 –

+0

結果異步就是我所需要的。感謝那個@piedar,它已經消除了用戶界面的壓力。不知道爲什麼遞歸會是一個壞主意,但它爲我完成了工作。 – Chrayfish

1

而不是一個同步遞歸方法,你應該寫一個異步迭代方法。

private async void Foo() 
{ 
    while(ShouldKeepLooping()) 
    { 
     SendKeys.Send(keyToSend); 
     await Task.Delay(timespan.FromSeconds(2)); 
    } 
} 

使方法遞歸沒有添加任何東西;使其迭代去除堆壓力。通過使該方法異步,而不是同步,您不會阻止UI線程。