MvvmLight, Messenger, and Async method calls - c#

I am using MvvmLight and have implemented communication between some of my ViewModels using the MessengerInstance.Send(...) method. It works great!
Recently, though, I have moved from using Synchronous methods to async methods to retrieve data and it looks like this breaks messaging (probably because it executes on a different thread). For example:
public ICommand SomeCommand { get { return new RelayCommand(DoSomething); } }
private async void DoSomething(object obj)
{
//Used to be SomeWcfService.DoSomething(); with some logic afterward
await SomeWcfService.DoSomethingAsync().ContinueWith(task => { //Some logic after method completes });
MessengerInstance.Send(SomeDataToSend, MessageIdentifer.DoSomething);
}

Instead of using a continuation, just put it after the await:
private async void DoSomething(object obj)
{
//Used to be SomeWcfService.DoSomething(); with some logic afterward
var result = await SomeWcfService.DoSomethingAsync();
// .ContinueWith(task => { //Some logic after method completes });
// use result here!
MessengerInstance.Send(SomeDataToSend, MessageIdentifer.DoSomething);
}
If there is no result returned from DoSomethingAsync, you can just leave out the result, and put your code in place.
The continuation, as you wrote it, will not run on the same synchronization context. The await keyword is actually asynchronously waiting your continuation, not the async method from WCF, as well.
If your "some logic" is asynchronous, you can use await within that code, as well.

Related

Can I use async and Task.Run to make a complex method asyncronous? [closed]

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)

Xamarin.ios run a WCF Service function using await

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.

Call async method with callback from sync UI thread [duplicate]

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.

Is this the correct way to write asynchronous methods?

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

How to return data using await function in C# windows phone 8?

I'm new to C#. I
I've a problem related to async methods and await function in C# windows phone 8.0.
I've this http request and can get response. This is working fine and There is no issue...
public async static Task<List<MyAccountData>> GetBalance()
{
HttpClient = new HttpClient();
string response = await client.GetStringAsync("http://xxxx/xxx/xxx");
List<MyAccountData> data = JsonConvert.DeserializeObject<List<MyAccountData>>(response);
return data;
}
I've another class call MainModel
public class MainModel
{
public void LoadData()
{
}
}
So My problem is, I want to call that GetBalance method with in MainModel class and parse data to LoadData method(simply want 2 access Data with in LoadData method). LoadData method can't change return type or can't use async. So how is this possible?
If you want a responsive UI - i.e., one that has a chance of being accepted in the store - then blocking on the async operation is not an option.
Instead, you have to think a bit about how you want your UI to look while the operation is in progress. And while you're thinking about that, also think about how you would want your UI to respond if the operation errors out.
Then you can code up a solution. It's possible to do this with async void, if you catch all exceptions and handle them cleanly:
public async void LoadData()
{
try
{
... // Set up "loading" UI state.
var balance = await GetBalanceAsync();
... // Set up "normal" UI state.
Balance = balance;
}
catch
{
... // Set up "error" UI state.
}
}
However, I prefer to use a type I created called NotifyTaskCompletion, which is a data-bindable wrapper for Task<T> (described in my MSDN article). Using NotifyTaskCompletion, the LoadData becomes much simpler:
public void LoadData()
{
GetBalanceOperation = new NotifyTaskCompletion<Balance>(GetBalanceAsync());
}
public NotifyTaskCompletion<Balance> GetBalanceOperation // Raises INotifyPropertyChanged when set
Then your UI can data-bind to properties on NotifyTaskCompletion<T>, such as IsNotCompleted (for the "loading" state), IsSuccessfullyCompleted and Result (for the "normal" state), and IsFaulted and ErrorMessage (for the "error" state).
There is no difference to use async await in Windows Phone 8 dev:
public class MainModel
{
public async void LoadData()
{
var data = await Foo.GetBalance();
}
}
Depends on whether you want LoadData to be synchronous (not returning until all the data has been streamed in over HTTP, and locking up the UI until then), or to begin the process and return immediately. If you can't change LoadData to async, then those are your only two options.
If you want LoadData to be synchronous:
public void LoadData() {
var task = GetBalance();
var result = task.Result; // will lock up the UI until the HTTP request returns
// now do something with result
}
If you want it to start a background process and return immediately, but for some reason don't want to mark LoadData as async:
public void LoadData() {
BeginLoadData();
}
private async void BeginLoadData() {
var result = await GetBalance();
// now do something with result
}
Though really, there's no reason not to go ahead and make LoadData async. async void does not force you to change the callers in any way (unlike Async<Task<T>>), and it's assignment-compatible with plain old non-async delegates:
public async void LoadData() {
var result = await GetBalance();
// now do something with result
}
// ...
LoadData(); // works just fine
Action myAction = LoadData; // works just fine
As you are working on asynchronus operations you need to wait until the operation is completed.The return type async/await method is always Task(TResult), to access the result of the async/await you need to use Result Property.The get accessor of Result property ensures that the asynchronous operation is complete before returning.
public void LoadData()
{
var data = GetBalance().Result;
}

Categories