views:

697

answers:

3

Lets say I am calling some web service method that I do not control. This method takes a long time to run, and whoever developed the web service did not think to include a asynchronous version.

What is the best way to create an asynchronous wrapper for such a method in C#/winforms?

At the moment I am using a ThreadPool to run the webservice method and then calling an event when the webservice finishes. Something like this.

DoWorkAsync() {
    Webservice.LongMethod()
    WorkCompleteEvent()
}

However, this doesn't appear to be ideal. For example, if I try to modify the form controls from the event handler I get a warning about not doing that from a different thread etc.

Does anyone have any other suggestions for solving this problem?

+6  A: 

See the MSDN article on How to: Make Thread-Safe Calls to Windows Forms Controls & also Jon Skeet's great guide to threading more specifically Threading in Windows Forms.

Quoting Jon (emphasis mine):

Never invoke any method or property on a control created on another thread other than Invoke, BeginInvoke, EndInvoke or CreateGraphics, and InvokeRequired. Each control is effectively bound to a thread which runs its message pump. If you try to access or change anything in the UI (for example changing the Text property) from a different thread, you run a risk of your program hanging or misbehaving in other ways. You may get away with it in some cases, but only by blind luck. Fortunately, the Invoke, BeginInvoke and EndInvoke methods have been provided so that you can ask the UI thread to call a method for you in a safe manner.

mundeep
A: 

You can use asynchronous delegates to call the web method. You can have a look at Asynchronous File Copy/Move in C# to see how it can be done. Consider FileCopy is your web method (rather than a class method as shown in the eg.)

For cross-thread errors you can refer to crossthread operations error

Rashmi Pandit
+1  A: 

The solution is to use built in asynchronous solution to the web services. Use the webservice.BeginLongMethod() to call and use the IAsyncResult. But remember that you must always use Invoke methods to update windows forms code since it is on a different thread.

See following articles

http://www.informit.com/articles/article.aspx?p=29395&seqNum=4

http://msdn.microsoft.com/en-us/library/ms228972.aspx

Shafqat Ahmed