Turn asynchronous calls into synchronous - c#

Is there any good practice (pattern) in turning asynchronous calls into synchronous?
I have a third party library who's methods are all asynchronos, to get result of almoust any method you must listen to an event, which will bring some context with it.
basically it looks like:
service.BeginSomething(...);
service.OnBeginSomethingCompleted += ;
what I need is to execute some code after BeginSomething when it is really complete (thus after OnBeginSomethingCompleted is triggered). It is very inconvinient to handle the response in the event.
The only way I could think of is running a Thread.Sleep loop and wait till some field on the form is updated, but it doesn't look like very elegant sollution.
I'm using .net 4.0.

You could subclass the main class and provide a synchronous version of the operation. If subclassing is not an option you could create an extension method. Here is how things might look.
public class Subclass : BaseClass
{
public void Something()
{
using (var complete = new ManualResetEventSlim(false))
{
EventHandler handler = (sender, args) => { complete.Set(); };
base.OnBeginSomethingCompleted += handler;
try
{
base.BeginSomething();
complete.Wait();
}
finally
{
base.OnBeginSomethingCompleted -= handler;
}
}
}
}
Update:
One thing I should have pointed out is that this could be problematic in some cases. Consider this example.
var x = new Subclass();
x.BeginSomething();
x.Something();
It should be obvious that the handler in Something could receive the OnBeginSomethingCompleted event from the previous call to BeginSomething. Make sure you guard against this somehow.

Use a ManualResetEvent. In your sync wrapper create it, then pass it to the service.BeginSomething() call as part of the state object. Immediately after the call, WaitOne() on it, this will block.
In the service.OnBeginSomethingCompleted event extract it from the state object and set it, this will unblock the sync caller.

As other said, if possible you should try to make your own code async. If that won't work, does your third-party library support the standard BeginXXX, EndXXX async pattern? If so, then using the TPL would make things easy for you. Your code will look something like this:
using System.Threading.Tasks;
...
var task = Task<TResult>.Factory.FromAsync(
service.BeginSomething, service.EndSomething, arg1, arg2, ..., null);
task.Wait();
var result = task.Result;
The specific overload you'll want to use will depend on how many parameters you need to pass. You can see the list here.

If BeginSomething() returns an IAsyncResult (like a delegate's .BeginInvoke would do), you can get the WaitHandle from that:
service.OnBeginSomethingCompleted += ;
var asyncResult = service.BeginSomething();
asyncResult.AsyncWaitHandle.WaitOne(); // Blocks until process is complete
By the way, by assigning the event handler after starting the async process, you are introducing a race condition where the async call may complete before the event is registered, causing it to never fire.

You might want to look at Reactive Extensions
With Rx you can wrap that into an 'event' basically - the do something like someClass.SomeEvent.Subscribe(d=>...) to subscribe using usually some lambda expression to handle what you need. Also use ObserveOn to handle it on the GUI thread (see the details, this is just a hint).
Other option is to use async await (which is now available for use with VS 2010).
hope this helps
NOTE: Rx have a native support for async methods and turning them into Rx events with pretty much just one call. Take a look at Observable.FromAsyncPattern FromAsyncPattern

The general trend of modern software development (on Windows platform too) is to run, what is possible asynchroniously.
Actually from Windows8 software design guidelines, if the code runs more then 50ms, it has to be asynchronious.
So I would not suggest to block the thread, but instead benefit from that library and provide to the user with some nice looking animation saying "wait, responce comming", or something like this, or some progress bar.
In short, do not block thread, notify a user about what is going on in app and leave it async.

This solution is similar to Brian Gideon's, but I think a little bit cleaner for what you're trying to do. It uses the Monitor object to cause the calling thread to wait until the Completed event is triggered.
public class SomeClass : BaseClass
{
public void ExecuteSomethingAndWaitTillDone()
{
// Set up the handler to signal when we're done
service.OnBeginSomethingCompleted += OnCompleted;
// Invoke the asynchronous method.
service.BeginSomething(...);
// Now wait until the event occurs
lock (_synchRoot)
{
// This waits until Monitor.Pulse is called
Monitor.Wait(_synchRoot);
}
}
// This handler is called when BeginSomething completes
private void OnCompleted(object source, ...)
{
// Signal to the original thread that it can continue
lock (_synchRoot)
{
// This lets execution continue on the original thread
Monitor.Pulse(_synchRoot);
}
}
private readonly Object _synchRoot = new Object();
}

Related

Cancel/Abort a Task in C#

I have a program in C# which does some services calls.
I need to add some code in this program in order to be able to stop these services calls if I click on a button (winform) [For example, if the call is too long and the user is bored].
The difficulty is that I can't modify the blocks of code which do the calls.
In order to do so, I've planned to do some Interception with the Unity Framework.
I would like to create a Task each time I enter a service-call block of code. Then, cancel this task if the user clicks on my Button.
I've looked about CancellationToken but the problem is that I can't modify the calls-blocks, so I can't do if(ct.IsCancellationRequested) or ct.ThrowIfCancellationRequested();
Same thing for the AutoResetEvent & ManualResetEvent.
The calls are not always asynchronous and made with a cancellationToken, so catching OperationCanceledExceptionis, I think, impossible.
I've also looked about using Threads and do some Thread.Abort() but this method seems to kill puppies each time someone calls it.
Here is a sample of my current program (the Interception is not implemented yet, I want to test it on a single call first) :
private void Test()
{
Task.Factory.StartNew(MyServiceCallFunction); // How to cancel the task when I press a button ?
}
// Can't touch the inside of this function :
private void MyServiceCallFunction()
{
// Blabla I prepare the datas for the call
// Blabla I do the call
}
How can I do that ? (I'm not obliged to use a task)
Thank you,
The "correct" way to do it is to used CancellationTokens but since you can't modify the running code the only other way is to kill the puppies and use Thread.Abort()
Something like:
Thread t;
Task.Factory.StartNew(() =>
{
t = Thread.CurrentThread;
MyServiceCallFunction();
});
t.Abort();
Very Interesting question. Of course you cannot do anything when the third party call is doing TPL; in your case it is MyServiceCallFunction().
I have been in the similar situation where this blog post has helped me: https://social.msdn.microsoft.com/Forums/vstudio/en-US/d0bcb415-fb1e-42e4-90f8-c43a088537fb/aborting-a-long-running-task-in-tpl?forum=parallelextensions
(read: Stephen Toub - MSFTMicrosoft (MSFT) comments)
He has mentioned this solution:
int Test(CancellationToken token)
{
Thread currentThread = Thread.CurrentThread;
using (token.Register(currentThread.Abort))
{
MyServiceCallFunction()
}
}
Also replace Task.Factory.StartNew (...) with Task.Run(...) ; same, infect latter is stronger, but better readable.

C# Events Multiple Publishers to One Subscriber

I have a piece of code that has two event handlers. I want these two event handlers to notify another method that there is some work to be done.
I have implemented this using a ManualResetEvent, but I am unsure if this is the best way to achieve what I want, or if there is some better way.
static ManualResetEvent autoEvent = new ManualResetEvent(false);
void begin() {
ThreadPool.QueueUserWorkItem(new WaitCallback(genericHandler));
}
void OnEvent1(object sender) {
autoEvent.Set();
}
void OnEvent2(object sender) {
autoEvent.Set();
}
void genericHandler(object info) {
while (true) {
autoEvent.WaitOne();
// do some work
}
}
One of the most important questions I have is: After autoEvent.WaitOne(), I do some work and that work consumes time. In the meanwhile, another event is triggered, and Set() is called before the genericHandler gets to WaitOne() again. When WaitOne is reached again, will it wait for another Set(), or proceed if a Set() has been called before reaching the WaitOne()?
Is this the best way to implement multiple publishers and one subscriber pattern in C#? Or should I use another thing instead of the ManualResetEvent?
Note: The genericHandler is in a different thread because Event1 and Event2 have different priorities, so in the handler I check whether Event1 has pending work, before checking Event2.
Your code does indeed do what you think it does, and the race condition you describe is not a problem at all. As per the documentation of a MRE, when it is set it will remain in the "signaled" state until it is reset by a call to WaitOne.
The question and code is presented too vaguely to offer good, specific advice. That said...
No, the use of ManualResetEvent is not appropriate here. Not only does it needlessly complicate the code, your code relies on a long-running thread that you have taken from the thread pool (where only short-lived tasks should be executed).
If you have a need for events to trigger the execution of some asynchronous work, then you should be using the async/await pattern, where each new unit of work is invoked via the Task class.
For example:
async void OnEvent1(object sender) {
var workUnit = ... ; // something here that represents your unit of work
await Task.Run(() => genericHandler(workUnit));
}
void OnEvent2(object sender) {
var workUnit = ... ; // something here that represents your unit of work
await Task.Run(() => genericHandler(workUnit));
}
void genericHandler(object info) {
// do some work using info
}
Note that the event object and the begin() method are eliminated entirely.
It's not clear from your question whether each work unit is entirely independent of each other. If not, then you may also require some synchronization to protect shared data. Again, without a more specific question it's not possible to say what this would be, but most likely you'd either use the lock statement, or one of the Concurrent... collections.

How to expose async method's event?

I have a webservice method getContactsAsync. I've understood that when it's completed it's supposed to raise an event. How can I (still asynchronously) find out when the method is done and use the result?
public void GetContacts()
{
webService.getContactsAsync()
}
public void GetContactsCompleted(object sender, getContactsAsyncCompletedEventArgs e)
{
contacts = e.Result;
}
I don't get how I'm supposed to use this. The way I can think of is to call GetContacts and then with a while-loop check if contacts != null to know when it has completed. But this will lock up the thread.
Is there some kind of best-practice typical for this situation?
Thanks for reading!
If I'm completely out of it feel free to explain how it actually works :)
Each DoSomethingAsync method has a corresponding DoSomethingCompleted event that is raised when the method finishes. (See Event-based Asynchronous Pattern Overview for more information.) You need to attach your event handler method to the webService.GetContactsCompleted event in order for it to be executed:
public void GetContacts()
{
webService.getContactsCompleted += GetContactsCompleted;
webService.getContactsAsync();
}
// NOTE: Should be a private method.
private void GetContactsCompleted(object sender, getContactsAsyncCompletedEventArgs e)
{ /* ... */ }
(Note that you will need to ensure that the event handler is only attached once, or it will start being invoked multiple times when the method finishes.)
If you are using SOAP-based web services via a Web Reference, this resource may be the ticket.
http://msdn.microsoft.com/en-us/library/wyd0d1e5%28VS.80%29.aspx
Another viable approach is to use the synchronous methods of the service from your own background thread.
I'm not familiar with that method, sounds specific to that web-service. However, to point you in the right direction, most Async methods take in a delegate as a parameter and will call that delegate when it has finished.
Depending on the method, there may be parameters to call for errors, status and so on.
It's hard to get more specific than that without more specific information about your situation.
Take a look at Calling Web Services Asynchronously.
It's a bit hard to figure out from your question where the problem lies.
You can keep track of when the operation completes by setting something in the event handler. In your example code, you're setting contacts, so you could just check if contacts is null.
If you want an asynchronous notification of completion, like an event that triggers when the operation completes, then... er... handle GetContractsCompleted, because that's exactly what it's there for.
If there's something more specific that you'd like (e.g., a WaitHandle that is signalled or a Task that completes when the operation completes), then that can be done but it's a bit more work.

How can I tell if a thread is finished executing without polling ThreadState?

Is there an elegant way to know when a worker thread is done executing so I can access resources it produced?
For example if the worker thread queried a list of SQL Servers using
ServersSqlDataSourceEnumerator.Instance.GetDataSources();
and saved the result in a DataTable variable, what mechanism can I use to know when this DataTable variable has been populated/is available. I don't want to poll ThreadState; it would be ideal to fire an event when it's done so I can perform actions with the result.
Thanks!
You can use a callback mechanism or block on an event to know of completion of an Async operation. See this page for the Asychronous Programming Model in .net - you can call BeginInvoke on any delegate to perform the action in an Async manner.
If you're using the BackgroundWorker type, you can subscribe to the RunWorkerCompleted event.
So fire an event :-P
You could also look at using an AutoResetEvent:
http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx
What I do in this instance is get the WorkerThread to call a function after it has completed the work, which will invoke the the UI Thread, which can do the work in which you require.
E.g.
private void SetWorkerThreadToDoWork()
{
WorkerThread.Start();
}
private void MyWorkerThreadWork()
{
//This will be on the WorkerThread (called from WorkerThread.Start())
DoWorkFunc();
WorkComplete();
}
private void WorkComplete()
{
if(InvokeRequired == true)
{
//Do the invoke
}
else
{
//Check work done by worker thread
//e.g. ServersSqlDataSourceEnumerator.Instance.GetDataSources();
}
}
If it's a simple process you're using, I'd go for a BackgroundWorkerThread, this comes with it's own events that are fired when work is complete. But if you require to use a Thread, I would either look in to Asynchronous Callbacks or a similar route to that shown above.
You can check my answer on this SO thread
It uses a call back mechanism. When the async operation is done, it will fire the callback method where you can handle the processing that needs to be done post SQL execution.
Use a similar approach to be notified when the asynchronous operation is done.
Hope this helps :)
I don't program in C# but here's what I did with Delphi, maybe you can do it as well with C#.
I have a TThread descendant, and in the "destroy" event I send a message to its creator saying "hey I'm about to die !".
This way its parent (which is the main thread) creates a new one if it needs a new one. To be precise it launches a timer that, when fired, creates a new thread if a new one is needed (sites sucking time (lol) !!).

Is it possible to put an event handler on a different thread to the caller?

Lets say I have a component called Tasking (that I cannot modify) which exposes a method “DoTask” that does some possibly lengthy calculations and returns the result in via an event TaskCompleted. Normally this is called in a windows form that the user closes after she gets the results.
In my particular scenario I need to associate some data (a database record) with the data returned in TaskCompleted and use that to update the database record.
I’ve investigated the use of AutoResetEvent to notify when the event is handled. The problem with that is AutoResetEvent.WaitOne() will block and the event handler will never get called. Normally AutoResetEvents is called be a separate thread, so I guess that means that the event handler is on the same thread as the method that calls.
Essentially I want to turn an asynchronous call, where the results are returned via an event, into a synchronous call (ie call DoSyncTask from another class) by blocking until the event is handled and the results placed in a location accessible to both the event handler and the method that called the method that started the async call.
public class SyncTask
{
TaskCompletedEventArgs data;
AutoResetEvent taskDone;
public SyncTask()
{
taskDone = new AutoResetEvent(false);
}
public string DoSyncTask(int latitude, int longitude)
{
Task t = new Task();
t.Completed = new TaskCompletedEventHandler(TaskCompleted);
t.DoTask(latitude, longitude);
taskDone.WaitOne(); // but something more like Application.DoEvents(); in WinForms.
taskDone.Reset();
return data.Street;
}
private void TaskCompleted(object sender, TaskCompletedEventArgs e)
{
data = e;
taskDone.Set(); //or some other mechanism to signal to DoSyncTask that the work is complete.
}
}
In a Windows App the following works correctly.
public class SyncTask
{
TaskCompletedEventArgs data;
public SyncTask()
{
taskDone = new AutoResetEvent(false);
}
public string DoSyncTask(int latitude, int longitude)
{
Task t = new Task();
t.Completed = new TaskCompletedEventHandler(TaskCompleted);
t.DoTask(latitude, longitude);
while (data == null) Application.DoEvents();
return data.Street;
}
private void TaskCompleted(object sender, TaskCompletedEventArgs e)
{
data = e;
}
}
I just need to replicate that behaviour in a window service, where Application.Run isn’t called and the ApplicationContext object isn’t available.
I've had some trouble lately with making asynchronous calls and events at threads and returning them to the main thread.
I used SynchronizationContext to keep track of things. The (pseudo)code below shows what is working for me at the moment.
SynchronizationContext context;
void start()
{
//First store the current context
//to call back to it later
context = SynchronizationContext.Current;
//Start a thread and make it call
//the async method, for example:
Proxy.BeginCodeLookup(aVariable,
new AsyncCallback(LookupResult),
AsyncState);
//Now continue with what you were doing
//and let the lookup finish
}
void LookupResult(IAsyncResult result)
{
//when the async function is finished
//this method is called. It's on
//the same thread as the the caller,
//BeginCodeLookup in this case.
result.AsyncWaitHandle.WaitOne();
var LookupResult= Proxy.EndCodeLookup(result);
//The SynchronizationContext.Send method
//performs a callback to the thread of the
//context, in this case the main thread
context.Send(new SendOrPostCallback(OnLookupCompleted),
result.AsyncState);
}
void OnLookupCompleted(object state)
{
//now this code will be executed on the
//main thread.
}
I hope this helps, as it fixed the problem for me.
Maybe you could get DoSyncTask to start a timer object that checks for the value of your data variable at some appropriate interval. Once data has a value, you could then have another event fire to tell you that data now has a value (and shut the timer off of course).
Pretty ugly hack, but it could work... in theory.
Sorry, that's the best I can come up with half asleep. Time for bed...
I worked out a solution to the async to sync problem, at least using all .NET classes.
Link
It still doesn't work with COM. I suspect because of STA threading. The Event raised by the .NET component that hosts the COM OCX is never handled by my worker thread, so I get a deadlock on WaitOne().
someone else may appreciate the solution though :)
If Task is a WinForms component, it might be very aware of threading issues and Invoke the event handler on the main thread -- which seems to be what you're seeing.
So, it might be that it relies on a message pump happening or something. Application.Run has overloads that are for non-GUI apps. You might consider getting a thread to startup and pump to see if that fixes the issue.
I'd also recommend using Reflector to get a look at the source code of the component to figure out what it's doing.
You've almost got it. You need the DoTask method to run on a different thread so the WaitOne call won't prevent work from being done. Something like this:
Action<int, int> doTaskAction = t.DoTask;
doTaskAction.BeginInvoke(latitude, longitude, cb => doTaskAction.EndInvoke(cb), null);
taskDone.WaitOne();
My comment on Scott W's answer seems a little cryptic after I re-read it. So let me be more explicit:
while( !done )
{
taskDone.WaitOne( 200 );
Application.DoEvents();
}
The WaitOne( 200 ) will cause it to return control to your UI thread 5 times per second (you can adjust this as you wish). The DoEvents() call will flush the windows event queue (the one that handles all windows event handling like painting, etc.). Add two members to your class (one bool flag "done" in this example, and one return data "street" in your example).
That is the simplest way to get what you want done. (I have very similar code in an app of my own, so I know it works)
Your code is almost right... I just changed
t.DoTask(latitude, longitude);
for
new Thread(() => t.DoTask(latitude, longitude)).Start();
TaskCompleted will be executed in the same thread as DoTask does. This should work.

Categories

Resources