How can i make this method async? - c#

I was wondering how i could make this method async, it gives me an error: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
Here's my code:
void OnRegister(object sender, RoutedEventArgs e)
{
await PrintManager.ShowPrintUIAsync();
}

You're welcome:
async void OnRegister(object sender, RoutedEventArgs e)
{
await PrintManager.ShowPrintUIAsync();
}
You can't use await without a async method(this would not make any sense).

async Task<int> OnRegisterAsync(object sender, RoutedEventArgs e)
{
await PrintManager.ShowPrintUIAsync();
return 0;
}

You need to decorate the method which contains 'await' with 'async'.
In your case I'm guessing you can't make OnRegister return a Task so you'll need a helper method. Something like this should work:
void OnRegister(object sender, RoutedEventArgs e)
{
RegisterAsync();
}
async void RegisterAsync() {
await PrintManager.ShowPrintUIAsync();
}
Notice how the RegisterAsync method is decorated with 'async' and returns a Task. Which in turn needs to be started by the caller.
Reference: http://msdn.microsoft.com/en-us/library/hh191443.aspx

Related

async function running in sequence WPF

so I am making a small WPF app.
I am new to C# and Multithreading, I want to run certain methods in sequence but because one of the methods is Async it does not run in sequence.
private async void LoadButton_Click(object sender, RoutedEventArgs e)
{
if (!OpenFile()) return; // opens a file dialog and ensure format is correct
await Task.Run(() =>
{
// some heavy task which I run here so that I dont freeze the UI
});
}
private void TheFunctionIwantToRunInSeqeuence(object sender, RoutedEventArgs e)
{
LoadButton_Click(sender, e);
SaveCareerInfoButton_Click(sender, e); // I want this line to wait for load to finish
LoadButton_Click(sender, e);
ImportCareerInfoButton_Click(sender, e); // I want this line to wait for the second load to finish
}
Await these calls as well, refactor your code a bit.. extract handler's content to a separate method and don't pass senders and args between handlers
private Task Load()
{
if (!OpenFile()) return;
return Task.Run(() =>
{
// some heavy task which I run here so that I dont freeze the UI
});
}
private async void LoadButton_Click(object sender, RoutedEventArgs e)
{
await Load();
}
private async void TheFunctionIwantToRunInSeqeuence(object sender, RoutedEventArgs e)
{
await Load();
// refactor your code to not pass sender, e.. SaveCareer();
SaveCareerInfoButton_Click(sender, e);
await Load();
// refactor your code to not pass sender, e.. ImportCareer();
ImportCareerInfoButton_Click(sender, e);
}
You can use await to wait an async function to finish and make function TheFunctionIwantToRunInSeqeuence to async Task return type:
private async Task TheFunctionIwantToRunInSeqeuence(object sender, RoutedEventArgs e)
{
await LoadButton_Click(sender, e);
SaveCareerInfoButton_Click(sender, e); // I want this line to wait for load to finish
await LoadButton_Click(sender, e);
ImportCareerInfoButton_Click(sender, e); // I want this line to wait for the second load to finish
}

This delegate does not work

I need to add an element to a Winform ListView control from other thread, so I am using a delegate, this way:
private delegate void AddMessageLogCallback(string message);
public void AddMessageLog(string message)
{
if (InvokeRequired)
Invoke(new AddMessageLogCallback(AddMessageLog), message);
else
{
lstLogs.Items.Add(message).EnsureVisible();
}
}
The problem is that the Invoke does nothing, not even throws an exception.
I have used this kind of delegates before and never had problems. What different is at this time?
Your code works as desired with the test code below, so the problem should be something else.
private void button1_Click(object sender, EventArgs e)
{
AddMessageLog("local message");
}
private async void button2_Click(object sender, EventArgs e)
{
await Task.Run(() => AddMessageLog("async message"));
}
Btw, I would mention that there is no need to define a new AddMessageLogCallback delegate and to call the AddMessageLog recursively. So a more simple (and maybe cleaner) solution:
public void AddMessageLog(string message)
{
Action addLog = () => lstLogs.Items.Add(message).EnsureVisible();
if (InvokeRequired)
Invoke(addLog);
else
addLog();
}

Convert method to return a task

How can I turn the below method into the right format for returning a task items. The method stub requires a task to be used. This is my first time into async methods I am using it for the windows phone 8 like below:
private System.Threading.Tasks.Task listView_PullToRefreshRequested(object sender, EventArgs e)
{
Populatelist();
}
public async void Populatelist()
{
try
{
curoListsDal _db = new curoListsDal();
cLists = await _db.GetListsAync();
listView.ItemsSource = cLists;
}
catch (Exception ex)
{
}
}
The right format would be to return a Task instead of void in PopulateListAsync and await on that inside your event handler:
private async void PullToRefreshRequestAsync(object sender, EventArgs e)
{
await PopulateListAsync();
}
public async Task PopulateListAsync()
{
curoListsDal db = new curoListsDal();
listView.ItemsSource = await db.GetListsAsync();
}
Side note: don't swallow exceptions.

Windows form breaks when calling Task.Result

I have code similar to following inside my Windows form:
private async Task<string> GetGreetingAsync()
{
return await Task.Run(() => "Hello");
}
private void button1_Click(object sender, EventArgs e)
{
var x = GetGreetingAsync().Result;
}
Clicking the button causes the entire Windows form to freeze and become unresponsive. No exception is thrown.
Even when I don't use the task .Result directly in the event handler and the whole async marked code is in some class library function, which provides interface without async, the problem still occurs. Unit tests for such class library pass without any problems, but when I call its function from event handler on Windows form, it breaks and does not respond.
Why does this happen? How can I fix it?
You are blocking the the UI thread with .Result; (see ConfigureAwait)
private async Task<string> GetGreetingAsync()
{
return await Task.Run(() => "Hello").ConfigureAwait(false);
}
private void button1_Click(object sender, EventArgs e)
{
var x = GetGreetingAsync().Result;
}
Or go all the way async
private async Task<string> GetGreetingAsync()
{
return await Task.Run(() => "Hello");
}
async private void button1_Click(object sender, EventArgs e)
{
var x = await GetGreetingAsync();
}
Using this version you don't even need to await in GetGreetingAsync
private Task<string> GetGreetingAsync()
{
return Task.Run(() => "Hello");
}
async private void button1_Click(object sender, EventArgs e)
{
var x = await GetGreetingAsync();
}
You should be using await instead of Result on a Task<T> to get non-blocking behavior.
private async void button1_Click(object sender, EventArgs e)
{
var x = await GetGreetingAsync();
}
Calling Result causes the code to wait until the Task has completed where calling await allows the async behavior to be used.
Edit
Actually looking at your code again if you're doing
private async Task<string> GetGreetingAsync()
{
return await new Task<string>(() => "Hello");
}
That is really not needed. That block can just be
private Task<string> GetGreetingAsync()
{
return new Task<string>(() => "Hello");
}
There's no need for the thing returning the task to be async.

Custom async Method

Is there a way to make an asynchronous call to a custom method in WP7 - WP8?
In a Windows Forms app i would simply do this:
private void btnStart_Click(object sender, EventArgs e)
{
MyMethod();
}
private async void MyMethod()
{
await System.Threading.Tasks.Task.Run(() => Thread.Sleep(5000));
}
However, it seems like the System.Threading.Tasks namespace is not supported in WP apps.
Then what should i do if i wished to act similarly in my WP7 - WP8 app?
You can install Microsoft.Bcl.Async for WP7.5 support. If you need WP7.0 support, your best bet is BackgroundWorker.
P.S. Your WinForms example would be better written as:
private async void btnStart_Click(object sender, EventArgs e)
{
await Task.Run(() => MyMethod());
}
private void MyMethod()
{
Thread.Sleep(5000);
}
Following these best practices:
Avoid async void.
Don't use Task.Run in general-purpose library methods.

Categories

Resources