I'm writing a application with a critical region.
And I decide to use AutoResetEvent to achieve mutual exclusion.
Here's the code
public class MyViewModel
{
private AutoResetEvent lock = new AutoResetEvent(true);
private aync Task CriticalRegion()
{
Dosomething();
}
public async Task Button_Click()
{
Debug.WriteLine("Entering Button_Click");
lock.WaitOne();
try
{
await CriticalRegion();
}
finally
{
lock.Set();
Debug.WriteLine("Leaving Button_Click");
}
}
}
I have a button whose click event calls the Button_Click() method
It works normally. But, if I'm quick enough to click the button for another time before the first call to Button_Click() completes, the whole app stops responding.
In the Debug window I find something like this
Entering Button_Click
Entering Button_Click
Looks like the method never completes.
I struggled a bit and find that if I change lock.WaitOne(); to
if (!sync.WaitOne(TimeSpan.FromSeconds(1)))
{
return;
}
In this case my app is able to avoid the deadlock,but I don't know why it works.
I only know about the IPC from my OS course and the async and await pattern in C#, and I'm not so familiar with the thread in .Net world.
I really want to understand what's really going on behind the scenes.
Thanks for any replys ;)
You have a deadlock because WaitOne is blocking the main thread (button click handler is executed on the main thread), while you haven't called ConfigureAwait(false) when calling await, which means that it tries to run the code which is after await on the main thread, even if it's blocked, which would causes a deadlock.
I suggest reading this post for a thorougher explanation of the dead lock situation.
For your code, I would suggest putting the lock deeper, probably within the async Task, and trying to use a more suitable pattern for locking, preferably, the lock statement, because using Event objects is awkward for mutual exclusion, as Hans stated in the comment.
AutoResetEvent.WaitOne() will block infinitely until you call AutoResetEvent.Set(), which you never seem to do except for after the WaitOne() call.
Quoting the AutoResetEvent.WaitOne() documentation:
Blocks the current thread until the current WaitHandle receives a signal.
Related
I have a multi-threaded UI application that starts numerous background threads. A lot of these threads execute code that looks as follows:
public void Update(){
if(Dispatcher.HasShutdownStarted()) return;
Dispatcher.Invoke(()=>{...});
...
}
Then I sometimes may have a thread execute the following code
pubic void Shutdown(){
if(Dispatcher.HasShutdownStarted()) return;
Dispatcher.InvokeShutdown();
}
The problem is that sometimes one thread executes Dispatcher.InvokeShutdown() AFTER another thread executed Dispatcher.HasShutdwonStarted() but before it got to Dispatcher.Invoke(()=>{...}). Which means, that there will be a thread trying to execute a lambda on the Dispatcher once the Dispatcher has begun to shut down. And that's when I get exceptions. What is the best solution to this?
The problem you face is that the HasShutdownStarted is checked, before the code inside the Invoke is executed (because it's queued on the dispatcher)
I think a better way is to check it inside the invoke, this way you don't need any locks.
public void Update(){
Dispatcher.Invoke(()=>
{
if(Dispatcher.HasShutdownStarted()) return;
...
});
}
With the help of others I managed to come up with the following solution to my problem and thought I'd share it. Calling Dispatcher.Invoke(...) after Dispatcher.InvokeShutdown() will always lead to a TaskCancelationException being thrown (as far as I can tell). Thus, checking Dispatcher.HasShutdownStarted inside of the Invoke method will not work.
What I did was create an application global CancellationToken by creating a static CancellationTokenSource. I now invoke the Dispatcher as follows:
Dispatcher.Invoke(()=>{...}, DispatcherPriority.Send, GlobalMembers.CancellationTokenSource.Token);
Then, when I wish to invoke shutdown on my dispatcher, I do the following:
GlobalMembers.CancellationTokenSource.Cancel();
Dispatcher.InvokeShutdown();
If by any chance I try to run Dispatcher.Invoke(()=>{...}, DispatcherPriority.Send, GlobalMembers.CancellationTokenSource.Token) after cancelling the global token and after invoking Dispatcher.InvokeShutdown(), nothing happens as the token is already cancelled and thus the action is not run.
I would like to stop a method until a custom delegate provides a callback from one method to a listener in another in Xamarin.Android, but I am having a lot of trouble understanding the implementation of such a listener.
I have only tried to understand how this could be done, but I'm stuck on how the delegate would be constructed and called.
Let's say that I want this MainActivity method to stop
public async override void OnWindowFocusChanged(bool hasFocus)
{
base.OnWindowFocusChanged(hasFocus);
//how can I create a listener to stop this method until callback from OnPause?
//await a delegate task?
}
and await another method inside a Fragment:
public override void OnResume()
{
base.OnResume();
//I'd like to implement a delegate here to notify the OnWindowFocusChanged that OnResume method has been invoked
//what would be the construction of such?
}
How could I do that?
From my research, I believe I would need to create a delegate task, and then await it's return in OnWindowFocusChanged. However, I am confused about the implementation of such a solution. If anyone could provide even a very basic pseudo-code example, it would help me out a lot.
EDIT: I changed OnPause to OnResume because that's more useful for understanding what I'm trying to do. The below answer references OnPause, but those two are extremely similar methods anyway.
Here is an example that almost does what I'm trying to do; except instead of starting my method when OnResume is invoked, OnWindowFocusChanged stops for 10000ms. So basically, I'd like to replace the timer with a custom delegate (similar to an event) task that returns when Fragment.OnResume is invoked.
public async override void OnWindowFocusChanged(bool hasFocus)
{
base.OnWindowFocusChanged(hasFocus);
//we won't pass this line for 10000ms; how to replace with Task return?
await WaitHere();
}
async Task WaitHere()
{
System.Threading.Thread.Sleep(10000);
}
You could try Task.Run method like:
await Task.Run(() => OnPause());
This would basically create a new thread or use the one you are on and schedule everything after this line as a continuation. So yes, the method would kinda stop, but unless you are on some GUI thread (not to block) or you run some IO task this is unnecessary.
I do not really understand what you are trying to achieve, but you might try to create new OnPauseAsync method that would return Task to get some result from the method when it finishes. This way you would get sequential like mechanism that doesn't block.
If you want to run those methods truly in parallel, but stop execution of OnWindowFocusChanged unitl something hapens in OnPause you should use bare Threads and some synchronization primitives like Mutex or Barrier. Then you would be able to make "main" thread wait until something happens (but it would block! beware). About those fellas you can read more here : LINK_WITH_FOCUS_ON_BARRIER
I am not really sure I got your intentions right, but I hope it helps somehow in the end.
To review:
if you just want to wait for the completion of OnPause and it does only CPU heavy things and you are not on UI thread - do not do anything as there is no profit in using threads etc.
if onPause does some IO heavy things you can use:
Tasks - potentially executed on one thread and doesn't block, control is returned to OnWindowFocusChanged AFTER onPause finishes completely.
Threads - if you want to run some parallel (two threads guaranteed) computations and wait for onPause to signal AT SOME POINT of execution to its caller that it might proceed, you can use e.g Barrier - but beware as this is the most complex solution from programmers perspective and it blocks if you are on UI thread.
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.
As an example suppose we have this:
public class MyClass
{
public async Task<bool?> MySynchronousNonBlockingFunction()
{
await here ...
return MyDialogResult;
}
}
and caller must call my function as below:
public async void Button_Click()
{
var instance = new MyClass();
var result = await instance.MySynchronousNonBlockingFunction();
if (result == true)
{
some work ...
}
}
But using Task for awaiting as a such, forces you to make your MySynchronousNonBlockingFunction() function async. And as a side effect you must call MyClass.MySynchronousNonBlockingFunction() only inside an async void to be worked as expected.
I think it is not well for the caller. Because a lazy developer in an application development team may call MySynchronousNonBlockingFunction() without await and then application will not works fine. I want handle this async operation in my code internally and not to the caller. To prevent this development mistakes. same as this one:
public void Button_Click()
{
var instance = new MyClass();
var result = instance.MySynchronousNonBlockingFunction();
if (result == true)
{
some work ...
}
}
In fact, i not want freeze the running thread by wait nor actually pause thread so it must be free to process other its works in another call stack again. Witch i want is actually same as the work of await keyword for a Task execution. is there another option to make this use? and what is your solution here to implement await behavior?
I know there is in c# some ways to lock an object full-fanced and force the execution stack to wait. (for example by using Monitor, or Mutex etc). And all the ways that i found in c# are blocking the running thread.
But, How can i implement awaiting manually? Is there another way to achieve this purpose?
In fact, i want pause ui thread from continue executing at a position, and then resume it again to continue execution in later (from CallStack snapshot position). But i not want freeze or actually pause therad so it must be free to process other its works in another call stack again. Witch i want is actually same as the work of await keyword for a Task execution. is there another option to make this use?
That's not how await works, though. await works by returning and then resuming just that method later. In particular, the call stack is not captured.
If you want to mess around with switching thread stacks, then check out fibers. However, there are no .NET bindings for the fiber APIs, and it's quite possible that a lot of .NET code will simply break if you try to use fibers instead of threads. Then there's the whole question of whether a fiber can actually be an STA context for UI elements; I'm really not sure about that one. In short, here be dragons.
and what is your solution here?
Well, a modal dialog - by definition - is supposed to block other dialogs and run a nested message loop.
If you don't want this behavior, then write modeless dialogs instead. I.e., call Show instead of ShowDialog.
GUI window handlers are message-driven state-machines. You must write code that reflects that. That means no, you cannot sanely just wait, and you should not try.
I am using WPF and DelegateCommand from PRISM and have the following problem:
I start an async operation like:
public async void ProgramDevice()
{
var result = await FirmwareLoader.DownloadFirmwareAsync();
}
Inside this method an event is fired which I registered to and should update my DelegateCommand so it can't be executed:
//UiCommand is of type DelegateCommand
Engine.IsProgrammedChanged +=
(s, e) => Dispatcher.Invoke(() => UiCommand.RaiseCanExecuteChanged());
Now I have the problem, that the RaiseCanExecuteChanged causes a deadlock (I checked and the Dispatcher.Invoke does not cause it, because when I e.g. show a MessageBox instead it works fine).
Am I doing something wrong or how can I work around this problem?
I see you've already solved your problem, but I thought I'd give a more general solution that will help you prevent such deadlocks in the future.
In your case, you could easily avoid this deadlock by using ConfigureAwait like this:
var result = await FirmwareLoader.DownloadFirmwareAsync().ConfigureAwait(false);
What this does is allows the continuation to be performed on a different thread than the original. Doing so is not always possible, since a lot of times you need the continuation to be performed on the UI thread, but for this question I don't believe that's the case. So basically, the best practice is to always use ConfigureAwait(false) unless you need to resume execution from the original thread.
This article explains in detail why these kind of deadlocks happen and how to avoid them. Another recommended read is Best Practices in Asynchronous Programming.
Found the problem:
It was not the RaiseCanExecuteChanged, but the actual CanExecute which is triggered by it. In there I had an AsyncLock which waited for the programming task to be finished, before returning the value I use to descide if UiCommand can be executed --> deadlock as the programming task triggered it...
I solved it by simple using the "sync" property (which does not use the lock and just returns the current value/stat) of the value I need.
Am I doing something wrong or how can I work around this problem?
Method Dispatcher.Invoke blocks working thread until UI thread makes all updates
UI thread uses some resources locked by working thread (through RaiseCanExecuteChanged -> CanExecute method chain in the above code) and blocks
Deadlock since worker thread waits for UI thread to finish update and UI thread waits worker thread to release locked resources
A possible way to ensure no deadlocks is to asynchronously invoke updates on UI thread using Dispatcher.BeginInvoke.
//UiCommand is of type DelegateCommand
Engine.IsProgrammedChanged +=
(s, e) => Dispatcher.BeginInvoke(() => UiCommand.RaiseCanExecuteChanged());
This way UI thread will wait for a moment when working thread releases locked resources and then will update. But there will be no deadlock.