2016-06-13 26 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线程。