I'm programming an API for my software, which has a lot of interfaces and my software just inherits them.
I want the API users to have the possibility to do something after X milliseconds, something like this :
public void PerformAction(Action action, int delay)
{
Task.Run(async delegate
{
await Task.Delay(delai);
Form.BeginInvoke(action);
// I invoke on the Form because I think its better that the action executes in my main thread, which is the same as my form's thread
});
}
Now i know that the Task is like a new Thread, I just want to know, is this bad for my software? Is there any other possible better way?
The method will get executed a lot, so I don't know whether this approach is good or bad
You should not be creating a new Task for this, you can instead make the method a Task, something like this:
public async Task PerformAction(Action action, int delay)
{
await Task.Delay(delay);
action(); //this way you don't have to invoke the UI thread since you are already on it
}
And then simply use it like this:
public async void Butto1_Click(object sender, EventArgs e)
{
await PerformAction(() => MessageBox.Show("Hello world"), 500);
}
public async Task PerformAction(Action action, int delay)
{
await Task.Delay(delay);
action();
}
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I have a complex method, this method make webRequest, access database and other jobs.
public string MyComplexMethod(params){
//Access db
//Make WebRequests
//...
}
I made this method asynchronous this way:
public async Task<string> MyComplexMethod(params)
{
//Access db
//Make WebRequests
//...
}
public async Task MyComplexMethodAsync(params)
{
await Task.Run(() => MyComplexMethod()).ConfigureAwait(false);
}
And I call my complex method this way:
public void OtherMethod()
{
//other stuff
MyComplexMethodAsync(params);
//other stuff
}
Can I use async and mainly Task.Run with such complex method?
Or there another way to make this method asynchronous?
To be wrapped by Task.Run method don't need to be asynchronous
public string MyComplexMethod() {}
public Task MyComplexMethodAsync()
{
return Task.Run(() => MyComplexMethod());
}
But using sample above don't make your method to be asynchronous in the way async-await works.
You mentioned that your complex method uses webservices and database queries - this makes your method to be perfect candidate for making it asynchronous.
async-await was designed mostly for working with external resources effectively without using extra threads for operations which only waiting for response and do nothing.
Only you need, it creates own asynchronous method for every operation which "touches" external resources, most of the "clients" already provide asynchronous methods for working with databases or web services.
// Access Db
public async Task<object> GetValueFromDatabaseAsync()
{
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(query, connection))
{
await connection.OpenAsync();
return await command.ExecuteScalarAsync();
}
}
// Make web request
public async Task<HttpResponseMessage> SendRequestToWebServiceAsync(SomeData data)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(webserviceUrl);
return await client.PostAsJsonAsync("api/values", data);
}
}
Then you end up with your asynchronous complex method
public async Task<string> MyComplexMethodAsync()
{
var value = await GetValueFromDatabaseAsync();
var data = new SomeData(value);
var response = await SendRequestToWebServiceAsync(data);
return response.StatusCode.ToString();
}
Interesting part of asynchronous approach, that after you starting using async-await methods in your application they starts spreading over whole application like a zombies :)
For using MyComplexMethodAsync yuo need change OtherMethod to be asynchronous too
public async Task OtherMethodAsync()
{
//other stuff
await MyComplexMethodAsync(params);
//other stuff
}
I think you're on the right path with async / await.
async tells the compiler that you are going to wrap everything in that method ContinueWith AFTER you reach the await keyword.
public void Something()
{
var task = new Task(() => DoWork());
task.ContinueWith(() => MoreWorkAfter());
task.Start();
}
//Is the same as
public async void Something()
{
var task = new Task(() => DoWork());
task.Start();
await Task;
MoreWorkAfter();
}
//Is also the same as
public async void Something()
{
var task = Task.Run(() => DoWork());
await Task;
MoreWorkAfter();
}
//Still the same as
public async void Something()
{
await Task.Run(() => DoWork());
MoreWorkAfter();
}
To make the method itself awaitable it has to return a Task object also because Task has the GetAwaiter() the await is looking for. Just remember that if you don't START the task it will await forever. So here's the same method written in an awaitable way for others.
public Task SomethingAsync()
{
return Task.Run(() => DoWork());
}
//Same as...
public async Task SomethingAsync()
{
await Task.Run(() => DoWork());
}
//And now in other methods you can....
public async void AnotherMethod()
{
await SomethingAsync();
//Do more work after it's complete.
}
Something to take away is that the Task is running on a new thread once it's started and to answer your question, yes it offloads the work. So for your original method keep it the same. The async method can Task.Run it like you've done.
public string MyComplexMethod(params)
{
//Access db
//Make WebRequests
//...
}
public async Task MyComplexMethodAsync(params)
{
await Task.Run(() => MyComplexMethod()).ConfigureAwait(false);
}
Something to note however; is that although you may call:
await MyComplexMethodAsync(params);
You have ConfigureAwait(false);
Which means any code after the task, in that method, will not be on the current context.
public async Task MyComplexMethodAsync(params)
{
//Main thread work here
await Task.Run(() => MyComplexMethod()).ConfigureAwait(false);//Background work here
//This will also be background work since CongfigureAwait(false);
}
public async Task MyComplexMethodAsync(params)
{
//Main thread work here
await Task.Run(() => MyComplexMethod()); //Background work here
//Main thread work here again since CongfigureAwait defaults to true;
}
And I say Main thread work but that assumes the Main thread called MyComplexMethodAsync.
The easiest way to grasp it is just imagine everything AFTER the await keyword is basically a new Action that gets called when the task is complete; just like using ContinueWith.
AND if there is code AFTER the await keyword in your method, it will BE SCHEDULED to run on the Main thread (considering the Main thread called the method to start with). Meaning it's a little like using Dispatcher.BeginInvoke if you've ever use it. The remaining portion get's queued to run on the Main thread in better terms. (Again, unless you put ConfigureAwait(false) and then it doesn't)
I've followed the following example which works well.
https://developer.xamarin.com/guides/cross-platform/application_fundamentals/web_services/walkthrough_working_with_WCF/
The only issue is, the example uses button clicks to load data. Now i have two separate calls different functions, and i need one to wait for the other, for example:
So when i call function2 for example, i want to wait for function1 first.
_client.function1Async();
_client.function2Async();
I could put the function2 call inside the function1Completed handler, but i was looking to use async wait with it. When i use async task, i get an error saying cannot await a void. But the web service async function in the example is a void
If i had 6 calls that i wanted to run, it would become very messy.
void _client_function1Completed(object sender,UpdateOrdersByWardCompletedEventArgs e
{
}
void _client_function2Completed(object sender,UpdateOrdersByWardCompletedEventArgs e
{
}
Hope this makes sense.
You could Task.ContinueWith
ContinueWith creates a continuation that executes asynchronously when task 1 completes.
var task1 = Task.Factory.StartNew( () => { func1(); } );
Task task2 = task1 .ContinueWith( (i) => { func2(); } );
Not sure if I understood well what you are trying to achieve, but I guess you can try something like this:
Given some lengthy (and blocking) methods:
public void func1()
{
Console.WriteLine("func1");
System.Threading.Thread.Sleep(5000);
}
public void func2()
{
Console.WriteLine("func2");
System.Threading.Thread.Sleep(5000);
}
You could add the ability to run the lengthy stuff asynchronously by doing this:
public async Task function1Async()
{
await Task.Run(() => {
func1();
});
}
public async Task function1Async()
{
await Task.Run(() => {
func2();
});
}
Now you can choose to run 'func1' and 'func2' either asynchronously or synchronously, for example:
function1Async().Wait(); // will block
function2Async(); // will run asynchronously
So, for your particular case, given that you already have the two async methods, I guess that all you need to do is to call them as shown above.
This question already has answers here:
The calling thread cannot access this object because a different thread owns it.WPF [duplicate]
(6 answers)
Closed 6 years ago.
Im really stuck here... I have a XAML Page UI and want to call an async function everytime the user interacts with the UI.
I use SignalR for networking:
public static class ProtocolClient
{
private static HubConnection hubConnection;
private static IHubProxy protocolHubProxy;
public static async void connect(string server)
{
hubConnection = new HubConnection(server);
protocolHubProxy = hubConnection.CreateHubProxy("ProtocolHub");
protocolHubProxy.On<Body>("BodiesChanged", body =>
//call a callback to return body
);
await hubConnection.Start(); //wait for connection
}
public static async void sendTouch(Touch touch)
{
Body body = await protocolHubProxy.Invoke<Body>("GetBodyForTouch", touch);
//call a callback to return body
}
}
UI:
public sealed partial class MainPage : Page
{
[...]
private void Canvas_PointerPressed(object sender, PointerRoutedEventArgs e)
{
[...]
switch (ptrPt.PointerDevice.PointerDeviceType)
{
case Windows.Devices.Input.PointerDeviceType.Mouse:
if (ptrPt.Properties.IsLeftButtonPressed)
{
//call sendTouch
}
break;
default:
break;
}
[...]
}
}
I need a callback which can modify the UI. How can I call connect and sendTouch out of the UI and pass them a callback?
You don't need a callback. Just add the code after the await hubConnection.Start(); statement. Your method is 'cut in multiple methods' and will 'continue' after the await comes back. The await works like a blocking statement, but will not freeze the gui.
public static async void connect(string server)
{
hubConnection = new HubConnection(server);
protocolHubProxy = hubConnection.CreateHubProxy("ProtocolHub");
protocolHubProxy.On<Body>("BodiesChanged", body =>
//call a callback to return body
);
await hubConnection.Start(); //wait for connection
// add code here.
}
When handling commands async (from gui events), don't forget to disable controls to prevent executing the command more than ones.
Don't use async void methods. If you don't need to return a value, use async Task - if you do, use async Task<SomeType>.
Then, when you need to call an async method (and by convention, these should be named like ConnectAsync and SendTouchAsync), await it:
await SendTouchAsync(...);
When the asynchronous workflow ends, your continuation will be marshalled back to the UI thread (because you awaited from within a synchronization context), and you can manipulate the UI easily.
await kind of appears to work when you use async void, but the problem is that the caller has no way of tracking the asynchronous workflow - as far as the caller is concerned, the method just ended right then and now, and the code in the caller continues as usual.
Make sure to mark Canvas_PointerPressed as async too - sadly, in this case, it must be async void. Make sure to never call the event handler directly - the UI thread can handle the callbacks correctly, your code can't. If you need the same logic from other methods, just separate it into a proper async Task method and await that from the event handler.
I'm currently trying to write async code and I have the feeling that my code is not too correct at all.
I have the following method:
public void Commit()
{
_context.SaveChangesToDatabase();
}
Don't judge the code here as this are only samples. Also, don't say that if I'm using Entity Framework, that they come packaged with Async methods already. I just want to understand the async concept here.
Let's say that the method SaveChangesToDatabase does takes seconds to complete.
Now, I don't want to wait for it so I create an async method:
public async Task CommitAsync()
{
await Task.Run(() => Commit());
}
Does this mean that if I have a method:
public void Method()
{
// Operation One:
CommitAsync();
// Operation Two.
}
Does this mean that my code on Operation two will be executed before CommitAsync() is even completed?
If not, please guide me in the right direction.
Update
Based on the remarks here that I'm ignoring my async method results, is this implementation better?
public Task<TaskResult> CommitAsync()
{
var task = new Task<TaskResult>(() =>
{
try { Commit(); }
catch (Exception ex)
{
return new TaskResult
{
Result = TaskExceutionResult.Failed,
Message = ex.Message
};
}
return new TaskResult { Result = TaskExceutionResult.Succeeded };
});
task.Start();
return task;
}
This does mean that I need to put the async modifier on the method that call this code so that I can await this which means continue with the current execution and return when this method has been completed.
Fire but don't forget
CommitAsync() returns a Task, but Method ignores the return value of CommitAsync completely -- so yes, the code will not wait but simply go on with what's after that. This is bad, because, if Commit() throws an exception, you will never see it. Ideally, every task should be waited on somewhere by someone, so you can at least see if it fails.
Let's say that you have no async alternative to SaveChangesToDatabase, but you'd like to use it in an async context anyway. You can use Task.Run to create a "fake-asynchronous" method, but this is not recommended (see below):
public Task CommitAsync() {
return Task.Run(() => Commit());
}
And then, assuming Method is doing something interesting with async (which the below code does not do since it's the only asynchronous operation in there):
public async Task MethodAsync() {
// Operation One:
await CommitAsync();
// Operation Two.
}
Assuming you do not want to wait, but you do want to do something if the task failed, you can use a separate method:
public void Method() {
// Operation One:
var _ = TryCommitAsync();
// Operation Two.
}
private async Task TryCommitAsync()
{
try
{
await CommitAsync();
}
catch (Exception ex)
{
Console.WriteLine(
"Committing failed in the background: {0}",
ex.Message
);
}
}
Getting back results
Let's suppose .Commit() does return something (like the number of records affected); a similar "fake-asynchronous" wrapper (again, not recommended - see below) would look like this:
public Task<int> CommitAsync() {
return Task.Run(() => Commit());
}
If you want this result, you can await the task immediately:
public async Task MethodAsync() {
// Operation One:
int recordsAffected = await CommitAsync();
// Operation Two.
}
Or, if you don't need it immediately, use await when you do:
public async Task MethodAsync() {
// Operation One:
Task<int> commit = CommitAsync();
// Operation Two.
// At this point I'd really like to know how many records were committed.
int recordsAffected = await commit;
}
Async: don't fake it
In general, you don't want to write wrappers like CommitAsync() because they mislead callers into thinking code will be asynchronous when it isn't really, which brings few benefits other than not blocking (which is still useful in UI code, but not as good as true asynchronous code which doesn't need to use worker threads for everything). In other words, you should use Task.Run in the invocation of a method, not as the implementation of a method.
So don't, as a habit, write wrappers like CommitAsync for every synchronous method you have -- instead you want to make a true CommitAsync that uses the async support of the underlying libraries/frameworks (SqlCommand.ExecuteReaderAsync(), etcetera.)
If you have no choice and must use Task.Run, then the appropriate usage would look more like:
// This method is in the UI layer.
public async Task MethodAsync() {
// Operation One:
// Commit() is a method in the DA layer.
await Task.Run(() => Commit());
// Operation Two.
}
Here
http://channel9.msdn.com/events/TechEd/NorthAmerica/2013/DEV-B318#fbid=
is a good explanation on how to work with async, and why you should avoid "async over sync", which is what you are doing now with
public Task CommitAsync() {
return Task.Run(() => Commit());
}
There are some scenarios where you can benefit from it, but if you are going to provide this as part of a library is NOT a good idea to make this.
If this code is ONLY and ONLY going to be used by your app, and you are sure what you are doing and dont have a wawy to call async methods inside your async method, just do it
I need to process tasks in sequence. So this class subscribed to some events.
When event is handled, asynchronous method must be added to Queue, and it might be executed when all previous tasks completed. At this moment it is realized as here:
But ProccessTasks method stops working when firs event is raised.
public class class view
{
private void ModelUpdatedEventHandler(object sender, EventArgs args)
{
taskQueue.Enqueue(new Task(() => Invalidate()));
}
private void MoveCubesEventHandler(object sender, MoveCheckerEventArgs args)
{
taskQueue.Enqueue(new Task(() => MoveCube(args.Move)));
}
private async Task Invalidate()
{
//code here
}
public async Task MoveChecker(Move move)
{
//code here
}
private async Task ProccessTasks()
{
while (true)
{
while (taskQueue.Count > 0)
{
Task task = taskQueue.Dequeue();
await task;
}
}
}
private async void UserControl_Loaded_1(object sender, RoutedEventArgs e)
{
await Task.Run(() => ProccessTasks());
}
}
The problem is that you're never starting your tasks, ever. You put unstarted tasks into the queue, and then you wait on the unstarted tasks when you pull them out.
Having said that, I would discourage you from just making that one small change. Generally, dealing with unstarted tasks is fairly error prone, as you've seen. I would suggest enqueing Action objects instead of Task objects. When you pull the action out of the queue, you can then either execute it, or if you want to maintain asynchrony, use Task.Run to run it in another thread.
You also don't need to call ProccessTasks using Task.Run. It's already asynchronous, so there's no need to run it in a background thread.