让我们说我正在调用一些我无法控制的Web服务方法。这种方法需要很长时间才能运行,而开发Web服务的人并不认为包含异步版本。
在C#/ winforms中为这种方法创建异步包装的最佳方法是什么?
目前我正在使用ThreadPool运行webservice方法,然后在webservice完成时调用事件。这样的事情。
DoWorkAsync() {
Webservice.LongMethod()
WorkCompleteEvent()
}
然而,这似乎并不理想。例如,如果我尝试从事件处理程序修改表单控件,我会收到一条警告,告知不要从其他线程等那样做。
有没有人有任何其他建议来解决这个问题?
答案 0 :(得分:6)
请参阅How to: Make Thread-Safe Calls to Windows Forms Controls上的MSDN文章&还有Jon Skeet很棒guide to threading更具体Threading in Windows Forms。
引用Jon(强调我的):
永远不要在除 Invoke , BeginInvoke , EndInvoke 或 CreateGraphics <之外的其他线程上创建的控件上调用任何方法或属性/ em>和 InvokeRequired 。 每个控件都有效地绑定到运行其消息泵的线程。 如果您尝试从其他线程访问或更改UI中的任何内容(例如更改Text属性),则可能会以其他方式冒着程序挂起或行为不当的风险。您可能会侥幸逃脱在某些情况下,但只有盲目的运气。 幸运的是,已经提供了Invoke,BeginInvoke和EndInvoke方法,以便您可以要求UI线程以安全的方式为您调用方法。
答案 1 :(得分:1)
解决方案是使用内置的Web服务异步解决方案。使用webservice.BeginLongMethod()来调用和使用IAsyncResult。但请记住,您必须始终使用Invoke方法来更新Windows窗体代码,因为它位于不同的线程上。
参见以下文章
http://www.informit.com/articles/article.aspx?p=29395&seqNum=4
答案 2 :(得分:-1)
您可以使用异步委托来调用Web方法。 您可以查看Asynchronous File Copy/Move in C#以了解如何完成此操作。考虑FileCopy是您的Web方法(而不是如图所示的类方法)
对于跨线程错误,您可以参考crossthread operations error