What is the correct method to implement a infinitely running task which executes an Async BigJob()? and can be stopped upon request
Hint: I am trying to learn [a] new method(s) to update my existing strategy.
I have this simple program (a tester) which has an Start and Stop button.
When Start pressed, I am starting the tester which is going to find and test available devices in range and test the hell our of them in infinite amount of rounds until the user presses the Stop button.
The important point is, the main process/action/bigJob() is and awaitble asynchronous process.
So I would pseudo code the whole thing as
Start
Round 1 starts
Async Main job starts
Async connect
Async Read
Async Write
Async disconnect
Nobody cancelled me yet
Round 1 finishes
Round 2 starts
.
.
.
Round 2 finishes
Round 3 starts
.
Stop pressed, hence break out.
Stop
So I am using BackgroundWorker to implement the infinite loop and Async/Await for the Connect, read, write and disconnect that I have written in C# under .Net 4.5
Since my sub-tasks such as Connect and .etc are async then my main task is async and pressing the Stop button stops my process since it eliminates the infinite while loop that I have with having
while (!bw.CancellationPending)
{
await MainTask();
...
}
but it doesn't fire the BackgroundWorker_RunWorkerCompleted event, which doesn't do me any harm HOWEVER it's killing me since the background worker doesn't work as it's supposed to and I just keep thinking "there should be a better way!".
So, I have been reading about so many new ideas, like why to use BackgroundWorker at all now that we have Async/await. Some were saying use Task.Run() it's magical. I even read recommendations and blogs about this godsend TPL Dataflow that I have never heard of. And so far I haven't found a method which is as structured, documented and layed-out as a BackgroundWorker. (unless it's such simple or a one liner which doesn't even need documentation or .etc) So, guys, what is the solution for this. Or better way to ask:
What is the correct method to implement a infinitely running task which executes an Async BigJob()? and can be stopped upon request
You should use CancellationTokenSource. But don't pass the Token to the Task.Run method and don't throw an exception. Simply check if cancellation was requested and then stop.
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;
Task.Run(
async () =>
{
while (!ct.IsCancellationRequested)
{
await ConnectAsync();
await ReadAsync();
await WriteAsync();
await DisconnectAsync();
}
});
cts.Cancel();
When you pass a CancellationToken to the Task itself(Task.Run(async () => ..., ct)), you can't use it inside the delegate. It will only cancel the task if cancellation was called before the task started running. After it has begun, calling Cancel won't have any effect.
Create a CancellationTokenSource and pass its Token to the async task. This will allow you to signal to your async tasks that cancellation is requested. More info: http://msdn.microsoft.com/en-us/library/hh873177(v=vs.110).aspx
I would strongly recommend everybody to have a read about three different methods of Asynchronous Programming Patterns and the use of the recent and preferred method Task-based Asynchronous Pattern (TAP)
Asynchronous Programming Model (APM)
Describes the legacy model that uses the IAsyncResult interface to
provide asynchronous behavior. This model is no longer recommended for
new development.
Event-based Asynchronous Pattern (EAP)
Describes the event-based legacy model for providing asynchronous
behavior. This model is no longer recommended for new development.
Task-based Asynchronous Pattern (TAP)
Describes the new asynchronous pattern based on the
System.Threading.Tasks namespace. This model is the recommended
approach to asynchronous programming in the .NET Framework 4 and later
versions.
Thanks to #SKall for pointing me to the right direction.
Related
I've read Stephen Toub's blog about making a custom awaitable for SocketAsyncEventArgs. This works all fine. But what I need is a cancellable awaitable and the blog doesn't cover this topic. Also Stephen Cleary unfortunately doesn't cover in his book how to cancel async methods that don't support cancellation.
I tried to implement it myself, but I fail with the TaskCompletionSource and Task.WhenAny because with the awaitable I'm not actually awaiting a task.
This is what I would like to have: being able to use Socket's ConnectAsync with TAP format and being able to cancel it, while still having the reusability of SocketAsyncEventArgs.
public async Task ConnectAsync(SocketAsyncEventArgs args, CancellationToken ct) {}
And this is what I have from Stephen Toub's blog so far (and the SocketAwaitable implementation):
public static SocketAwaitable ConnectAsync(this Socket socket,
SocketAwaitable awaitable)
{
awaitable.Reset();
if (!socket.ConnectAsync(awaitable.m_eventArgs))
awaitable.m_wasCompleted = true;
return awaitable;
}
I just can't figure out how to get this into the TAP format and making it cancellable.
Any help is appreciated.
Edit 1:
This is the example how I would do cancellation normally:
private static async Task<bool> ConnectAsync(SocketAsyncEventArgs args, CancellationToken cancellationToken)
{
var taskCompletionSource = new TaskCompletionSource<bool>();
cancellationToken.Register(() =>
{TaskCompletionSource.Task
taskCompletionSource.TrySetCanceled();
});
// This extension method of Socket not implemented yet
var task = _socket.ConnectAsync(args);
var completedTask = await Task.WhenAny(task, taskCompletionSource.Task);
return await completedTask;
}
custom awaitable for SocketAsyncEventArgs.
This is doable, but SocketAsyncEventArgs is specifically for extremely performance-sensitive scenarios. The vast majority (and I mean >99.9%) of projects do not need it and can use TAP instead. TAP is nice because it interoperates well with other techniques... like cancellation.
what I need is a cancellable awaitable and the blog doesn't cover this topic. Also Stephen Cleary unfortunately doesn't cover in his book how to cancel async methods that don't support cancellation.
So, there's a couple of things here. Starting with "how to cancel async methods that don't support cancellation": the short answer is that you can't. This is because cancellation is cooperative; so if one side can't cooperate, it's just not possible. The longer answer is that it's possible but usually more trouble than it's worth.
In the general case of "cancel an uncancelable method", you can run the method synchronously on a separate thread and then abort that thread; this is the most efficient and most dangerous approach, since aborted threads can easily corrupt application state. To avoid this serious corruption problem, the most reliable approach is to run the method in a separate process, which can be terminated cleanly. However, that's usually overkill and way more trouble than it's worth.
Enough of the general answer; for sockets specifically, you cannot cancel a single operation, because this leaves the socket in an unknown state. Take the Connect example in your question: there's a race condition between the connection and the cancel. Your code might end up with a connected socket after it requests cancellation, and you don't want that resource sticking around. So the normal and accepted way to cancel a socket connection is to close the socket.
The same goes for any other socket operation: if you need to abort a read or write, then when your code issues a cancel, it can't know how much of the read/write completed - and that would leave the socket in an unknown state with regard to the protocol you're using. The proper way to "cancel" any socket operation is to close the socket.
Note that this "cancel" is at a different scope than the kind of cancellation we normally see. CancellationToken and friends represent the cancellation of a single operation; closing a socket cancels all operations for that socket. For this reason, the socket APIs do not take CancellationToken parameters.
Stephen Cleary unfortunately doesn't cover in his book how to cancel async methods that don't support cancellation. I tried to implement it myself
The question "how do I cancel an uncancelable method" is almost never properly solved with "use this code block". Specifically, the approach you used cancels the await, not the operation. After a cancel is requested, your application is still trying to connect to the server, and may eventually succeed or fail (both results would be ignored).
In my AsyncEx library, I do have a couple of WaitAsync overloads, which allow you to do something like this:
private static async Task MyMethodAsync(CancellationToken cancellationToken)
{
var connectTask = _socket.ConnectAsync(_host);
await connectTask.WaitAsync(cancellationToken);
...
}
I prefer this kind of API because it's clear that it's the asynchronous wait that is cancelled, not the connection operation.
I fail with the TaskCompletionSource and Task.WhenAny because with the awaitable I'm not actually awaiting a task.
Well, to do something more complex like this, you'll need to convert that awaitable to a Task. There may be a more efficient option, but that's really getting into the weeds. And even if you figure out all the particulars, you'll still end up with "fake cancelling": an API that looks like it cancels the operation but it really doesn't - it just cancels the await.
This is what I would like to have: being able to use Socket's ConnectAsync with TAP format and being able to cancel it, while still having the reusability of SocketAsyncEventArgs.
TL;DR: You should close the socket instead of cancelling a connection operation. That's the cleanest approach in terms of reclaiming resources quickly.
I am pretty sure, this was answered already and I read many related stuff but somehow I am not getting it to work in my code. Here is the exact code base.
I have this async method in my library, that returns a string upon doing some DB entries:
public class MyLibrary
{
public async Task<string> DoSomethingAsync()
{
return await DoAsync();
}
// some private method, with multiple parameters
private Task<string> DoAsync()
{
return Task.Run(() => Do());
}
}
Now on UI, below resulted a frozen state or deadlock:
var myTask = MyLibraryobject.DoSomethingAsync();
console.Write(myTask.Result);
Since my call is awaitable, I think, UI thread waits for my call to finish its business and populate the result, doesn't it? Or since the call is running on another thread, the task might not yet completed when my cursor hits the line 2. So what now? the cursor will wait till the task gets completed or the line 2 gets executed whenever the task gets completed? sounds synchronous to me..
Also if at all, I want to 'exlicitly' wait till the task gets finished, how do i enforce that? some posts, suggested in doing like below, which gave me the result, but created some more confusion:
var myTask = Task.Run(async () => await MyLibraryobject.DoSomethingAsync());
myTask.Wait();
console.Write(myTask.Result);
What is happening above? why should i create another task and set it to wait? can't I wait for the thread, used by the async method? Again, i am clearly missing some basic stuff here.
Lastly, this is an async call, but the UI thread is waiting for it to be completed thus gives me an impression that it's synchronous. Am I thinking it right? Then what is the main purpose of async methods, which return something, and UI waits for it to complete?
Also what's the difference between a fire-and-forget call being non-async and async? is there any benefit of returning Task, instead of void, for such calls?
I am pretty sure, some broken link that connects all these pieces together in my brain. Can someone explain that to me, please??
You should probably start with my async intro and follow up with my article on async best practices. They answer almost all your questions.
For the details...
how and when to fetch return from awaitable(async) method
You should use await to get the result from an async task.
I have this async method in my library, that returns a string upon doing some DB entries
Then it should not be using Task.Run. It should be using naturally-asynchronous APIs, e.g., Entity Framework's FirstAsync.
Since my call is awaitable, I think, UI thread waits for my call to finish its business and populate the result, doesn't it?
No. The UI is blocking because your code is calling Result. Result is a blocking call.
sounds synchronous to me..
That's because you're making it synchronous by using Result. If you use await, the code will execute serially, but asynchronously.
Also if at all, I want to 'exlicitly' wait till the task gets finished, how do i enforce that?
Your code is already doing that. It's explicitly blocking until the task is complete. If you change it to properly use await, it will be explicitly waiting (but not blocking) until the task is complete.
some posts, suggested in doing like below
No. Don't use Task.Run unnecessarily.
can't I wait for the thread, used by the async method?
Pure async methods don't have threads that they use.
Then what is the main purpose of async methods, which return something, and UI waits for it to complete?
Async makes sense when it's consumed with await.
Now on UI, below resulted a frozen state or deadlock:
var myTask = MyLibraryobject.DoSomethingAsync();
This is blocking the UI because it is not awaited. You simply need to await an async method
string res = await MyLibraryobject.DoSomethingAsync();
and the above should be placed in the UI inside an async context too.
Edit - reply to comment do "you mean another wrapper async method, which returns Task<string>..."? No,I don't. When I wrote "inside an async context" I meant to add the async keyword to a subscribed event, like a button click, if you are in the code behind or to your delegate command implementation, if you are in a more advanced MVVM implementation of the GUI.
Furthermore, your class library is supposed to do something truly asynchronous, not just starting a task and wrapping it inside a formally async method, like it is your DoAsync.
Edit - in reply to comment "how should avoid" it? If you can't do async all the way, just keep the library and the API sync and unblock the UI by starting a separate thread to call the sync api.
I have been looking into upgrading the way that we do async tasks in our software. For years the software has been running in .net 2.5 and the team previous, decided to implement their own async task architecture which for the most part is OK but difficult to use for more complicated things.
I was watching a tutorial which explained tasks in C# really well but then started looking at async methods and the await keyword to keep the software up to date. My question is, why you would want to use async and await over just creating a task and using .wait/.waitAll/.waitAny.
I have read things that say that it isn't creating new threads (which suggests its not as parallel) and that it has a performance overhead.
Can you still apply the wait all one by one methodology? I am guessing since the async returns a task you would just use this to populate your list but that just furthers my argument on why would you bother using it?
My question is, why you would want to use async and await over just
creating a task and using .wait/.waitAll/.waitAny.
A task is merely a promise of your which will complete in the future. Task != Thread , and that is an important thing to remember.
I have read things that say that it isn't creating new threads (which
suggests its not as parallel) and that it has a performance overhead.
That depends on how the Task is being created.
For example:
public async Task<string> GetPageAsync(string url)
{
var httpClient = new HttpClient();
var response = await httpClient.GetAsync(url);
return response.Content.ReadAsStringAsync();
}
This operations generates no threads, but still returns a Task<string>. using async-await has some overhead because under the covers, the compiler creates a state-machine which manages the execution flow, which has to take care of many things.
While this:
return Task.Run(FooOperation);
Requests a thread pool thread to run FooOperation on.
A task can be generated for doing overlapped IO (like the first example) operations which require no thread at all. When you create a task and use Wait/WaitAll/WaitAny, you're blocking on the call, and then you end up asking yourself why use that at all and not run it synchronously instead?
For async-await, you can use the asynchronous WhenAny/WhenAll, which themselfs yield an awaitable which can be asynchronously waited.
I've designed and made a prototype application for a high performance, multi-threaded mail merge to run as a Windows Service (C#). This question refers to one sticky part of the problem, what to do if the process hangs on a database call. I have researched this a lot. I have read a lot of articles about thread cancellation and I ultimately only see one way to do this, thread.Abort(). Yes, I know, absolutely do not use Thread.Abort(), so I have been researching for days how to do it another way and as I see it, there is no alternative. I will tell you why and hopefully you can tell me why I am wrong.
FYI, these are meant as long running threads, so the TPL would make them outside the ThreadPool anyway.
TPL is just a nice wrapper for a Thread, so I see absolutely nothing a Task can do that a Thread cannot. It's just done differently.
Using a thread, you have two choices for stopping it.
1. Have the thread poll in a processing loop to see if a flag has requested cancellation and just end the processing and let the thread die. No problem.
2. Call Thread.Abort() (then catch the exception, do a Join and worry about Finally, etc.)
This is a database call in the thread, so polling will not work once it is started.
On the other hand, if you use TPL and a CancellationToken, it seems to me that you're still polling and then creating an exception. It looks like the same thing I described in case 1 with the thread. Once I start that database call (I also intend to put a async / await around it), there is no way I can test for a change in the CancellationToken. For that matter, the TPL is worse as calling the CancellationToken during a Db read will do exactly nothing, far less than a Thread.Abort() would do.
I cannot believe this is a unique problem, but I have not found a real solution and I have read a lot. Whether a Thread or Task, the worker thread has to poll to know it should stop and then stop (not possible when connected to a Db. It's not in a loop.) or else the thread must be aborted, throwing a ThreadAbortedException or a TaskCanceledException.
My current plan is to start each job as a longrunning thread. If the thread exceeds the time limit, I will call Thread.Abort, catch the exception in the thread and then do a Join() on the thread after the Abort().
I am very, very open to suggestions... Thanks, Mike
I will put this link, because it claims to do this, but I'm having trouble figuring it out and there are no replys to make me think it will work
multi-threading-cross-class-cancellation-with-tpl
Oh, this looked like a good possibility, but I don't know about it either Treating a Thread as a Service
You can't actually cancel the DB operation. The request is sent across the network; it's "out there" now, there's no pulling it back. The best you can really do is ignore the response that comes back, and continue on executing whatever code you would have executed had the operation actually completed. It's important to recognize what this is though; this isn't actually cancelling anything, it's just moving on even though you're not done. It's a very important distinction.
If you have some task, and you want it to instead become cancelled when you want it to be, you can create a continuation that uses a CancellationToken such that the continuation will be marked as canceled when the token indicates it should be, or it'll be completed when the task completes. You can then use that continuation's Task in place of the actual underlying tasks for all of your continuations, and the task will be cancelled if the token is cancelled.
public static Task WithCancellation(this Task task
, CancellationToken token)
{
return task.ContinueWith(t => t.GetAwaiter().GetResult(), token);
}
public static Task<T> WithCancellation<T>(this Task<T> task
, CancellationToken token)
{
return task.ContinueWith(t => t.GetAwaiter().GetResult(), token);
}
You can then take a given task, pass in a cancellation token, and get back a task that will have the same result except with altered cancellation semantics.
You have several other options for your thread cancellation. For example, your thread could make an asynchronous database call and then wait on that and on the cancellation token. For example:
// cmd is a SqlCommand object
// token is a cancellation token
IAsyncResult ia = cmd.BeginExecuteNonQuery(); // starts an async request
WaitHandle[] handles = new WaitHandle[]{token.WaitHandle, ia.AsyncWaitHandle};
var ix = WaitHandle.WaitAny(handles);
if (ix == 0)
{
// cancellation was requested
}
else if (ix == 1)
{
// async database operation is done. Harvest the result.
}
There's no need to throw an exception if the operation was canceled. And there's no need for Thread.Abort.
This all becomes much cleaner with Task, but it's essentially the same thing. Task handles common errors and helps you to do a better job fitting all the pieces together.
You said:
TPL is just a nice wrapper for a Thread, so I see absolutely nothing a Task can do that a Thread cannot. It's just done differently.
That's true, as far as it goes. After all, C# is just a nice wrapper for an assembly language program, so I see absolutely nothing a C# program can do that I can't do in assembly language. But it's a whole lot easier and faster to do it with C#.
Same goes for the difference between TPL or Tasks, and managing your own threads. You can do all manner of stuff managing your own threads, or you can let the TPL handle all the details and be more likely to get it right.
I have such question. For example I create dynamically custom userControl using mvvm pattern. So I've sended a command to create an userControl. So creation looks like
private async Task<bool> OnAddUserControl1(List<ALV_VM_ADWERT> control)
{
try
{
_cancellationTokenSource = new CancellationTokenSource();
var userControl = _userControlsContainer.CreateUserControl1(control);
var task1 = Task.Factory.StartNew(() =>
{
userControl.ViewModel.InOperationEvent += OnUsercontrolInOperationChanged;
userControl.ViewModel.ValueTypeChangedEvent += OnValueTypeChanged;
userControl.ViewModel.SetExpandableName += OnSetExpandableName;
}, _cancellationTokenSource.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.FromCurrentSynchronizationContext());
var task2 = Task.Factory.StartNew(() => FinalCreatingStep(userControl, control[0].RAUMNAME.Trim()), _cancellationTokenSource.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.FromCurrentSynchronizationContext());
await Task.WhenAll(task1, task2);
return true;
}
catch (Exception)
{
return false;
}
}
and my question is - does it make sence to create child tasks, or it is better to have code without child tasks? And if the answer is yes, then should I make all methods async? If not, what methods I should not make async?
Do those event subscriptions really need to be asynchronous? You may be trying too hard to use asynchronous code.
The user control constructor is usually the most time consuming part and must be done on the UI thread. Asynchronous operations are generally only required when some form of IO or processing is involed;
Reading Files
Writing Files
Processing large data sets
Crossing the process boundary to talk to a server or connect device
In short, an asynchronous task is probably overkill here.
Does it make sence to create child tasks, or it is better to have code without child tasks?
It is depending on your requirements. If your UI will blocked (Freeze) for long time you have to create a child task, otherwise not!
And if the answer is yes, then should I make all methods async? If not, what methods I should not make async?
Here it is also depending on your requirements and your .Net Version. If you are using .NET 4.5 the easiest way to do that with Async await. If you are using .Net 3.5 than just use Task. If .Net 2 use BackgorundWorker else use Thread class. ONLY Asynchrony methods must get the word async. Other methods you do not have to change them. In other words only the method which blocked the UI.
Your current code doesn't make any sense.
The point of async code in a UI application is responsiveness - i.e., moving long-running operations off the UI thread. As #Gusdor pointed out, most of the use cases for async are I/O-based (or event-based) operations, where you don't want to block the UI thread just to wait for some result. Another use case is when you have some CPU-bound work to do, but you don't want to tie up the UI thread; in this case, you can use Task.Run.
But in your code, you're calling StartNew with TaskScheduler.FromCurrentSynchronizationContext, which means your "child" tasks are going to execute on the UI thread. So your OnAddUserControl1 is just starting tasks which will run on the same thread and asynchronously waiting for them to complete. This is a very complex way of doing nothing.
While we're on the subject of StartNew, there are a number of other problems:
The code is passing a CancellationToken without ever observing it in the delegate.
The code is specifying AttachedToParent which is incorrect for await-compatible tasks.
As mentioned above, the code is passing a TaskScheduler which will run the delegate right back on the UI thread.
If you need to use background (thread pool) tasks, you should use Task.Run instead of Task.Factory.StartNew; I go into more detail on my blog.
So for this example, it doesn't make sense to use async or await at all.
The best way to start using async is to identify the I/O-bound (or event-driven) parts first (e.g., HTTP requests, database calls), make them async, and then work your way up the call stack.