Is there a generic way to synchronize an asynchronous method? - c#

We have this common scenario where we have a method that performs some action asyncronously and raises an event when it's done.
There are times where we want it done synchronously instead so we have code that looks similar to this:
ManualResetEvent reset = new ManualResetEvent(false);
someobject.AsyncActionDone += (sender, args) => reset.Set();
someobject.PerformAsyncAction();
reset.WaitOne();
Is there a way to write a helper method to do this? I can pass in the Action to perform, but I'm not sure how to pass in something that lets the helper method know which event to listen to since it doesn't look like you can pass in an EventHandler as a parameter.
Preferably a solution that doesn't require reflection
There seems to be some confusion, this is a sample of what someobject's class is like:
public class SomeClass
{
private ExternalServer someServerOverTheNetwork = new ExternalServer();
public event EventHandler AsyncActionDone;
public Data SomeData { get; set; }
public void PerformAsyncAction()
{
someServerOverTheNetwork.GetSomeData(OnDataRetrived);
}
public Data OnDataRetrived(Data someData)
{
AsyncActionDone(this, new DataEventArgs(someData));
}
}

I would consider implementing the Asynchronous Design Pattern in the objects that performs asynchronous operation.
public object Operation(object arg)
{
var ar = BeginOperation(arg, null, null);
return EndOperation(ar);
}
public IAsyncResult BeginOperation(object arg, AsyncCallback asyncCallback, object state)
{
AsyncResult asyncResult = new AsyncResult(asyncCallback, state);
// Lauch the asynchronous operation
return asyncResult;
}
private void LaunchOperation(AsyncResult asyncResult)
{
// Do something asynchronously and call OnOperationFinished when finished
}
private void OnOperationFinished(AsyncResult asyncResult, object result)
{
asyncResult.Complete(result);
}
public object EndOperation(IAsyncResult asyncResult)
{
AsyncResult ar = (AsyncResult)asyncResult;
return ar.EndInvoke();
}
With this pattern you have the flexibility of having multiple concurrent asynchronous operation on your object.
Note: You can easily find an implementation of a generic AsyncResult class on the web.
Edit:
As you want to keep the current design, if all your object can only have one asynchronous operation, then you could define an IAsyncOperation interface and implement it in all your object.
public interface IAsyncOperation
{
event EventHandler AsyncActionDone;
void PerformAsyncAction();
}
Then you could have:
public static CallSynchronously(IAsyncOperation asyncOperation)
{
ManualResetEvent reset = new ManualResetEvent(false);
asyncOperation.AsyncActionDone += (sender, args) => reset.Set();
asyncOperation.PerformAsyncAction();
reset.WaitOne();
}
If your objects can contain multiple asynchronous operation, then without reflection I think there is no way to achieve what you want to do, but you could still define a synchronous version of all asynchronous operation that wraps the ManualResetEvent.
public void PerformAction()
{
ManualResetEvent reset = new ManualResetEvent(false);
this.AsyncActionDone += (sender, args) => reset.Set();
this.PerformAsyncAction();
reset.WaitOne();
}

If i catch your drift, you can simply use delegates in the following way,
create a delegate for you function call, lets call it
public delegate string AsyncDelegate();
then, create a proxy function like this:
public static void ExecuteSync(AsyncDelegate func)
{
ManualResetEvent reset = new ManualResetEvent(false);
int threadId;
func.BeginInvoke((a)=>reset.Set(), null);
reset.WaitOne();
}
Thats all, you can make it a bit more complex by adding another function delegate to run after completion or something like that..
Enjoy!

Related

ManualResetEvent WaitOne blocks the owner Thread of my CollectionView

I've written a WPF WizardFramework which performs some actions in the background using some BackgroundWorker. While processing it can happen that I have to update an ObservableCollection which is bound to my UI.
For this case I've written a ThreadableObservableCollection, which provides threadsafe methods for Insert, Remove and RemoveAt. Though I'm using .NET 4.5 I was not able to get BindingOperations.EnableCollectionSynchronization working without many other invalid access exceptions. My Collection looks like:
public class ThreadableObservableCollection<T> : ObservableCollection<T>
{
private readonly Dispatcher _dispatcher;
public ThreadableObservableCollection()
{
_dispatcher = Dispatcher.CurrentDispatcher;
}
public void ThreadsafeInsert(int pos, T item, Action callback)
{
if (_dispatcher.CheckAccess())
{
Insert(pos, item);
callback();
}
else
{
_dispatcher.Invoke(() =>
{
Insert(pos, item);
callback();
});
}
}
[..]
}
This is working as expected, while I am using the wizard in my application. Now I'm using NUnit to write some integrationtests for the application.
There's a listener which waits for the WizardViewModel to finish it's work and looking for some pages which are injected in the Steps-Collection. After the asyncrone work is done I can use Validate to check the viewmodel state.
Unfortunately I'm using a ManualResetEvent to wait for the wizard to close. This looks like following:
public class WizardValidator : IValidator, IDisposable
{
private WizardViewModel _dialog;
private readonly ManualResetEvent _dialogClosed = new ManualResetEvent(false);
[..]
public void ListenTo(WizardViewModel dialog)
{
_dialog = dialog;
dialog.RequestClose += (sender, args) => _dialogClosed.Set();
dialog.StepsDefaultView.CurrentChanged += StepsDefaultViewOnCurrentChanged;
_dialogClosed.WaitOne();
}
[..]
}
Now there's a problem:
While the Application is running the UI Thread is not blocked, the Collection can be updated without any problems. But in my testcases the "main" Thread where I initialize the ViewModel (and because of that the Collections) is an AppDomainThread which is blocked by the testcode. Now my ThreadsafeInsert wants to update the collection but cannot use the AppDomain Thread.
But I have to wait for the wizard to finish, how can I solve this kind of deadlock? Or is there a more elegant solution for this one?
edit:
I worked around this problem with a check if there's a user interface, and only then I invoke on the Application-Thread, otherwise I change the collection intentionally on another thread. This does not prevent the exception, but it is not recognized from the test... the items are inserted nevertheless, only the NotifyCollectionChanged-Handler is not called (which is only used in the UI anyway).
if (Application.Current != null)
{
Application.Current.Dispatcher.Invoke(() =>
{
Steps.Insert(pos, step);
stepsView.MoveCurrentTo(step);
});
}
else
{
new Action(() => Steps.Insert(pos, step)).BeginInvoke(ar => stepsView.MoveCurrentToPosition(pos), null);
}
This is an ugly workaround and I am still interested in a clean solution.
Is there a way to use an alternate Dispatcher to create (e.g.) the whole ViewModel and use this to change my collection?
As I see the main problem that main thread is blocked and other operations are trying to be executed in main thread too? What about not to block main thread, like this:
// helper functions
public void DoEvents()
{
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
new DispatcherOperationCallback(ExitFrame), frame);
Dispatcher.PushFrame(frame);
}
public object ExitFrame(object f)
{
((DispatcherFrame)f).Continue = false;
return null;
}
// in your code:
while(!_dialogClosed.WaitOne(200))
DoEvents();
If it will not help then I guess need to try some SynchronisationContext workarounds.
I think the problems boil down to the fact that you create ObservableCollection that is tied to Dispatcher object.
Involving Dispatcher object directly is almost never good idea(as you just witnessed). Instead I would suggest you to see how others have implemented ThreadSafeObservableCollection. This is a little example I put together, it should illustrate the point:
public class ThreadSafeObservableCollection<T> : ObservableCollection<T>
{
private readonly object _lock = new object();
public ThreadSafeObservableCollection()
{
BindingOperations.CollectionRegistering += CollectionRegistering;
}
protected override void InsertItem(int index, T item)
{
lock (_lock)
{
base.InsertItem(index, item);
}
}
private void CollectionRegistering(object sender, CollectionRegisteringEventArgs e)
{
if (e.Collection == this)
BindingOperations.EnableCollectionSynchronization(this, _lock);
}
}

Call a method (with an argument) after a delay

I want to pass a variable into a function that is run after a delay. I've seen similar question on how to do this (see below). I dont think this is what I want as I each time method1 is called, the number of attached anonymous functions grows? What I need to do is remove any existing attached anonymous function before adding the new one. But I dont think this possible. Is there a way to call a method after a delay but pass in a new value of a variable each time?
using System.Timers;
myTimer = new Timer();
myTimer.Interval = 3000;
myTimer.AutoReset = false;
public void method1(int var1){
myTimer.Elapsed += delegate { doSomething(var1); };
myTimer.Start();
}
public void doSomething(int arg1){...}
UPDATE
Basically whenever method1 is run, I want something to happen 3 secs later, and I need to pass in an argument that may vary each time.
I dont think I can use a field to store the variable because method1 may be called several times before the first timer expires. I.e. there could be several qued up. E.g. at one point in time the que of 'doSomething' waiting to happen could be...
doSomething(3)
doSomething(7)
doSomething(1)
It is just used in a testbench, and method1 will be run called no more than 50 times. What I want to ensure is that each doSomething(var1) only gets called once and not every 3 secs. Ie there is only one doSomething called each time method1 is called.
This is for a windows console app.
Using the TPL (& .Net 4.5), you can do something like this:
public static class ActionExtensions
{
public static async void DelayFor(this Action act, TimeSpan delay)
{
await Task.Delay(delay);
act();
}
}
//usage
Action toDo = () => doSomething(var1);
toDo.DelayFor(TimeSpan.FromSeconds(3));
... or this may be simpler for your app:
static async void DoSomethingLater(int n)
{
await Task.Delay(TimeSpan.FromSeconds(3));
//DoSomething(n);
}
//usage
void Method1(int n)
{
DoSomethingLater(n);
}
There's no good way to do that using System.Timers.Timer.
With System.Threading.Timer, you can pass a userState object to the constructor. That object is then passed to the timer callback with every tick. For example:
string Whatever = "foo";
System.Threading.Timer timer =
new System.Threading.Timer(MyTimerCallback, whatever, 100, 100);
void MyTimerCallback (object state)
{
string theData = (string)state;
// at this point, theData is a reference to the "Whatever" string.
// do tick processing
}
You could, if you want, extend System.Timers.Timer, and add a property to hold your data. Something like:
class DerivedTimer : System.Timers.Timer
{
public string Foo { get; set; }
}
myTimer = new DerivedTimer();
myTimer.Interval = 3000;
public void methodRunRegularly(int var1){
myTimer.Foo = "Foobar!";
myTimer.Elapsed += doSomething;
myTimer.Start();
}
public void doSomething(object sender, EventArgs e)
{
var t = (DerivedTimer)sender;
var foo = t.Foo;
// do processing
}
A reference to the timer is passed in the sender parameter. You can just cast that and then reference the Foo property that you set when you initialized the timer.
This makes use of Reactive Extensions (use nuget package "rx-main").
Run a method with a 3 second delay:
public void method1(int value)
{
ThreadPoolScheduler.Instance.Schedule(
TimeSpan.FromSeconds(3), () => doSomething(value));
}
That's about as short as it gets!

DownloadStringCompletedEventHandler callback in another class

I have two classes, below is a break down on what's going on before I go on to ask my question...
myClass1:
myClass1(){
myClass2 c2 = new myClass2();
c2.service();
}
public void myFunction1(){
Console.Write("Function returned!");
}
myClass2:
public void service(){
callWebService(myFunction1); // The parameter you pass here is the function that control
// will pass back to once the called function is done.
}
public void callWebService(DownloadStringCompletedEventHandler callback){
//Calls web service and does some other operations
}
And finaly the question. As you can see above I have the 2 classes, class1 calls a function in class2. That function calls another function also in class2 that calls a webservice. Once that web serivce is done control flow passes back to whatever function you passes in the function call.
But that means you're stuck to one class since the callback function should be in the same class. So the question is, how can I pass a function in another class to be the callback function?
Hope all this makes sense, please don't hesitate asking anything to clear things up a bit more. Thanks!
You can modify the Service class and pass MyClass1's method to it.For e.g In the below code , the function ServiceCallComplete is passed as a parameter to the Service class constructor.
The function can be saved as either Action or Func delegate type(depending on your callback function definition).Once the service job is done ,calling the delegate(_callBack()) will invoke the callback function on MyClass1.
public class MyClass1
{
//The callback Function
public void ServiceCallComplete()
{
Console.WriteLine("Function returned.");
}
}
public class Service
{
//delegate to store the callback function.
private readonly Action _callBack;
public Service(Action callBack)
{
//store the callback function
_callBack = callBack;
}
public void Method()
{
//long running operation
.
.
//Invoke the callback
_callBack();
}
}
MyClass1 obj = new MyClass1();
Service svc = new Service(obj.ServiceCallComplete);
svc.Method();
Instead of passing a delegate, use an event:
class MyClass1
{
public MyClass1()
{
var c2 = new MyClass2();
c2.ActionwebServiceCalled += MyCallBack; //register for the event
c2.CallWebService();
}
public void MyCallBack(object sender, DownloadStringCompletedEventArgs e)
{
Console.Write("Function returned!");
}
}
class MyClass2
{
public event DownloadStringCompletedEventHandler ActionwebServiceCalled;
public void CallWebService()
{
DownloadStringCompletedEventArgs e = null;
//Calls web service and does some other operations...
var handler = ActionwebServiceCalled;
if (handler != null)
handler(this, e);
}
}
Having said that, you'd might want to introduce asynchrony to the web service call, in which case the Task-based Asynchronous Pattern (TAP) is the way to go, provided that you have .NET 4 (or Rx). For .NET 3.5 and lower, you'll want to follow the Asynchronous Programming Model (APM).

How to cancel a deeply nested process

I have a class that is a "manager" sort of class. One of it's functions is to signal that the long running process of the class should shut down. It does this by setting a boolean called "IsStopping" in class.
public class Foo
{
bool isStoping
void DoWork() {
while (!isStopping)
{
// do work...
}
}
}
Now, DoWork() was a gigantic function, and I decided to refactor it out and as part of the process broke some of it into other classes. The problem is, Some of these classes also have long running functions that need to check if isStopping is true.
public class Foo
{
bool isStoping
void DoWork() {
while (!isStopping)
{
MoreWork mw = new MoreWork()
mw.DoMoreWork() // possibly long running
// do work...
}
}
}
What are my options here?
I have considered passing isStopping by reference, which I don't really like because it requires there to be an outside object. I would prefer to make the additional classes as stand alone and dependancy free as possible.
I have also considered making isStopping a property, and then then having it call an event that the inner classes could be subscribed to, but this seems overly complex.
Another option was to create a "Process Cancelation Token" class, similar to what .net 4 Tasks use, then that token be passed to those classes.
How have you handled this situation?
EDIT:
Also consider that MoreWork might have a EvenMoreWork object that it instantiates and calls a potentially long running method on... and so on. I guess what i'm looking for is a way to be able to signal an arbitrary number of objects down a call tree to tell them to stop what they're doing and clean up and return.
EDIT2:
Thanks for the responses so far. Seems like there's no real consensus on methods to use, and everyone has a different opinion. Seems like this should be a design pattern...
You can go two ways here:
1) The solution you've already outlined: pass a signaling mechanism to your subordinate objects: a bool (by ref), the parent object itself cloaked in an interface (Foo: IController in the example below), or something else. The child objects check the signal as needed.
// Either in the MoreWork constructor
public MoreWork(IController controller) {
this.controller = controller;
}
// Or in DoMoreWork, depending on your preferences
public void DoMoreWork(IController controller) {
do {
// More work here
} while (!controller.IsStopping);
}
2) Turn it around and use the observer pattern - which will let you decouple your subordinate objects from the parent. If I were doing it by hand (instead of using events), I'd modify my subordinate classes to implement an IStoppable interface, and make my manager class tell them when to stop:
public interface IStoppable {
void Stop();
}
public class MoreWork: IStoppable {
bool isStopping = false;
public void Stop() { isStopping = true; }
public void DoMoreWork() {
do {
// More work here
} while (!isStopping);
}
}
Foo maintains a list of its stoppables and in its own stop method, stops them all:
public void Stop() {
this.isStopping = true;
foreach(IStoppable stoppable in stoppables) {
stoppable.Stop();
}
}
I think firing an event that your subclasses subscribe to makes sense.
You could create a Cancel() method on your manager class, and on each of your other worker classes. Base it on an interface.
The manager class, or classes that instantiate other worker classes, would have to propagate the Cancel() call to the objects they are composed of.
The deepest nested classes would then just set an internal _isStopping bool to false and your long-running tasks would check for that.
Alternatively, you could maybe create a context of some sort that all the classes know about and where they can check for a canceled flag.
Another option was to create a
"Process Cancelation Token" class,
similar to what .net 4 Tasks use, then
that token be passed to those classes.
I am not familiar with this, but if it is basically an object with a bool property flag, and that you pass into each class, then this seems like the cleanest way to me. Then you could make an abstract base class that has a constructor that takes this in and sets it to a private member variable. Then your process loops can just check that for cancellation.
Obviously you will have to keep a reference to this object you have passed into your workers so that it's bool flag can be set on it from your UI.
Your nested types could accept a delegate (or expose an event) to check for a cancel condition. Your manager then supplies a delegate to the nested types that checks its own "shouldStop" boolean. This way, the only dependency is of the ManagerType on the NestedType, which you already had anyway.
class NestedType
{
// note: the argument of Predicate<T> is not used,
// you could create a new delegate type that accepts no arguments
// and returns T
public Predicate<bool> ShouldStop = delegate() { return false; };
public void DoWork()
{
while (!this.ShouldStop(false))
{
// do work here
}
}
}
class ManagerType
{
private bool shouldStop = false;
private bool checkShouldStop(bool ignored)
{
return shouldStop;
}
public void ManageStuff()
{
NestedType nestedType = new NestedType();
nestedType.ShouldStop = checkShouldStop;
nestedType.DoWork();
}
}
You could abstract this behavior into an interface if you really wanted to.
interface IStoppable
{
Predicate<bool> ShouldStop;
}
Also, rather than just check a boolean, you could have the "stop" mechanism be throwing an exception. In the manager's checkShouldStop method, it could simply throw an OperationCanceledException:
class NestedType
{
public MethodInvoker Stop = delegate() { };
public void DoWork()
{
while (true)
{
Stop();
// do work here
}
}
}
class ManagerType
{
private bool shouldStop = false;
private void checkShouldStop()
{
if (this.shouldStop) { throw new OperationCanceledException(); }
}
public void ManageStuff()
{
NestedType nestedType = new NestedType();
nestedType.Stop = checkShouldStop;
nestedType.DoWork();
}
}
I've used this technique before and find it very effective.
Litter your code with statements like this wherever it is most sensible to check the stop flag:
if(isStopping) { throw new OperationCanceledException(); }
Catch OperationCanceledException right at the top level.
There is no real performance penalty for this because (a) it won't happen very often, and (b) when it does happen, it only happens once.
This method also works well in conjunction with a WinForms BackgroundWorker component. The worker will automatically catch a thrown exception in the worker thread and marshal it back to the UI thread. You just have to check the type of the e.Error property, e.g.:
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
if(e.Error == null) {
// Finished
} else if(e.Error is OperationCanceledException) {
// Cancelled
} else {
// Genuine error - maybe display some UI?
}
}
You can flatten your call stack by turning each DoWork() call into a command using the Command pattern. At the top level, you maintain a queue of commands to perform (or a stack, depending on how your commands interact with each other). "Calling" a function is translated to enqueuing a new command onto the queue. Then, between processing each command, you can check whether or not to cancel. Like:
void DoWork() {
var commands = new Queue<ICommand>();
commands.Enqueue(new MoreWorkCommand());
while (!isStopping && !commands.IsEmpty)
{
commands.Deque().Perform(commands);
}
}
public class MoreWorkCommand : ICommand {
public void Perform(Queue<ICommand> commands) {
commands.Enqueue(new DoMoreWorkCommand());
}
}
Basically, by turning the low-level callstack into a data structure you control, you have the ability to check stuff between each "call", pause, resume, cancel, etc..

AsyncCallback for a thread on compact framework

I need to implement threading to improve load time in a compact framework app. I want to fire off a background thread to do some calls to an external API, while the main thread caches some forms. When the background thread is done, I need to fire off two more threads to populate a data cache.
I need the background thread to be able to execute a callback method so I know it's done and the next two threads can be started, but the BeginInvoke method on a delegate is not supported in the compact framework, so how else can I do this?
You can arrange it yourself, simply make sure your thread method calls a completed method (or event) when it's done.
Since CF doesn't support the ParameterizedThreadStart either, I once made a little helper class.
The following is an extract and was not re-tested:
//untested
public abstract class BgHelper
{
public System.Exception Error { get; private set; }
public System.Object State { get; private set; }
public void RunMe(object state)
{
this.State = state;
this.Error = null;
ThreadStart starter = new ThreadStart(Run);
Thread t = new Thread(starter);
t.Start();
}
private void Run()
{
try
{
DoWork();
}
catch (Exception ex)
{
Error = ex;
}
Completed(); // should check Error first
}
protected abstract void DoWork() ;
protected abstract void Completed();
}
You are required to inherit and implement DoWork and Completed. It would probably make sense to use a < T> for the State property, just noticed that.
I know this is an old question, but if you are using CF 3.5 this would be a nice an short solution to the problem. Using lambda delegate..
ThreadStart starter = () => DoWorkMethodWithParams( param1, param2);
Thread myNewThread = new Thread(starter){IsBackground = true};
myNewThread.Start();

Categories

Resources