window phone - method is not run ? - c#

I create a method in class :
public async void Foo()
{
.....
string response = await Utilities.sendData(data);
....
}
I create break point and run,when it call foo method,but break point run at
string response = await Utilities.sendData(data)
and then break point is disappear,if i call in code behind (xaml)it no problem

You can call an async method from synchronous code.
The async modifier says that the code within that method can await on other async methods. Here's a silly example
public class Foo
{
public void DoSomething()
{
await Something(); //invalid
Something(); //valid
}
public async void Something()
{
await SomethingElse(); //valid
SomethingElse(); // also valid, but synchronous
}
public async void SomethingElse()
{
}
}

Related

Executing several async function on one object

I'm curious is it possible to execute function Function1 and function Function2 in C# webapi project like in example below.
Both of these functions are on the same class and use async and await but return different types.
Example code below:
[ApiController]
[Route("[controller]")]
public class ClassController : ControllerBase
{
// ...
public async Task<ActionResult<string>> Test()
{
var message = await _myClass.Function1().Function2();
return Ok(message);
}
// ...
}
Declaration of _myClass looks like below:
public class MyClass
{
// ...
public async Task<MyClass> Function1()
{
// code which uses `await` below
// ....
// end of this code
return this;
}
public async Task<string> Function2()
{
// code which uses `await` below
// ....
// end of this code
return "some text";
}
}
Yes, you can do this:
public async Task<ActionResult<string>> Test()
{
var message = await
_myClass.Function1().ContinueWith(resultingMyClass =>
resultingMyClass.Result.Function2());
return Ok(message);
}
But the most obvious solution would be to use the async/await syntax that C# provides:
public async Task<ActionResult<string>> Test()
{
var result1 = await _myClass.Function1();
var message = await result1.Function2();
return Ok(message);
}
If you don't need the result from the first call as input to the second function you can run multiple Tasks in parallel and wait until they have all finished using Task.WhenAll.

Function as parameter in async method

I call a method containing a function:
public void DoMagicStuff(Func<T> anyfunction) {
// do lots of magic stuff
}
This works:
public void DoNonAsyncStuff() {
DoMagicStuff(()=> {
AnotherFunction();
}
}
While this does not:
public async Task<CustomClass> DoAsynStuff() {
DoMagicStuff(()=> {
return await DoSomethingDifferent();
}
}
"The await operator can only be used in async functions"
How do I make this work for async methods?
If you intend to pass asynchronous delegates to DoMagicStuff, then you need to overload that with an asynchronous version:
public void DoMagicStuff(Func<T> anyfunction)
{
// do lots of magic stuff
T t = anyfunction();
}
public async Task DoMagicStuff(Func<Task> asyncfunction)
{
// do lots of magic stuff
T t = await asyncfunction();
}
This allows you to call await for the asyncfunction.
Any common logic can always be refactored into another method.
With regard to your question, await can only be used in a function that has been declared async, which your lambda hasn't.
It should be like this:
public async Task<CustomClass> DoAsynStuff()
{
await DoMagicStuff(async () =>
{
return await DoSomethingDifferent();
});
}
And in fact, because DoSomethingDifferent already returns a Task, the lambda is superfluous:
public async Task<CustomClass> DoAsynStuff()
{
await DoMagicStuff(DoSomethingDifferent);
}

(A)wait for class to finish instantiate

I try to wait for the class to be finished with instantiate.
My architecture is the following. Cook is inheriade from CookChief.
And if I instantiate cook, CookChief is creating himself, but CookChief is calling 1 other class named Cookhelper the cookhelper is waiting for a input and for this input method i want to wait in Cook.
The thing is iam creating this in MVVM Galasoft and my entry point is the CookViewmodel, with a relaycommand.
In the code below you can see my architecture. To say it short I want to wait until this bool processed = await Task.Run(() => ValidateForDeviceId()); is finished.
My first step was to outsource the constructer of each class. And create a init method.
This is my code:
public CookViewModel()
{
startCookButtonCommand = new RelayCommand(Cook);
}
private async Task Cook()
{
cook.Init();
}
public class Cook : CookChief
{
public Cook()
{
}
public async Task Init()
{
await this.CookChiefInit();
//here I want to wait until CookChiefInit is finished
Cooking();
}
public void Cooking()
{
MessageBox.Show("Input received");
}
}
Now the Cookchief:
public Cookchief()
{
}
protected async Task CookchiefInit()
{
this.Cookhelper = new Cookhelper();
Cookhelper.CookHelperInit();
}
And in the CookHelper we do this:
public CookHelper()
{
}
public void CookHelperInit()
{
this.driverWindow = new DriverWindow();
startProc();
}
private async void startProc()
{
ShowOrCloseDriverWindow(true);
//this is the task what we wait for before we can repeat
bool processed = await Task.Run(() => ValidateForDeviceId());
if(processed)
{
ShowOrCloseDriverWindow(false);
}
else
{
MessageBox.Show("DriverError");
}
}
private bool ValidateForDeviceId()
{
for (; ; )
{
this.deviceId = Input.deviceId;
if (deviceId > 0)
{
break;
}
}
return true;
}
Per the discussion in the comments, the problem here was that the initialization routine mixed synchronous and asynchronous methods and calls. Additionally, some async methods were called without the await keyword. The solution was to make all calls asynchronous and await them.
cook.Init() needs an await:
private async Task Cook()
{
await cook.Init();
}
In CookchiefInit(), the CookHelperInit() call needs to be awaited:
protected async Task CookchiefInit()
{
this.Cookhelper = new Cookhelper();
Cookhelper.CookHelperInit();
}
In order to await CookHelperInit(), it needs to be made asynchronous. The startProc() call is to an async method, so it must also be awaited:
public async Task CookHelperInit()
{
this.driverWindow = new DriverWindow();
await startProc();
}

Testing property set by async method

I try to test a class with NUnit that contains async methods. I don't know how to do it in a correct way.
I have a class with that looks like this:
public class EditorViewModel:INotifyPropertyChanged
{
public void SetIdentifier(string identifier)
{
CalcContentAsync();
}
private async void CalcContentAsync()
{
await SetContentAsync();
DoSomething();
}
private async Task SetContentAsync()
{
Content = await Task.Run<object>(() => CalculateContent());
RaisePropertyChanged("Content");
}
public object Content { get; private set; }
...
}
How can I write a Test in NUnit, that checks, that the Content-Property is set to the right value? I want to do something like that:
[Test]
public void Content_WhenModifierIsXXX_ReturnsSomeViewModel()
{
var viewModel = new EditorViewModel();
viewModel.SetIdentifier("XXX");
Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>());
}
But that doesn't work. Because the asynchronous code has not been executed before the assertion.
Your SetIdentifier method is async too (or you need to make it async because you wait operation inside it. Then your method can looks like next one:
public async Task SetIdentifier(string identifier)
{
await SetContentAsync();
DoSomething();
}
And now you can just await it in your unit test:
[Test]
public async Task Content_WhenModifierIsXXX_ReturnsSomeViewModel()
{
var viewModel = new EditorViewModel();
await viewModel.SetIdentifier("XXX");
Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>());
}
You can also use workaround to call your test in a sync manner:
[Test]
public async Task Content_WhenModifierIsXXX_ReturnsSomeViewModel()
{
Task.Run(async () =>
{
var viewModel = new EditorViewModel();
await viewModel.SetIdentifier("XXX");
Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>());
}).GetAwaiter().GetResult();
}
Via MSDN Magazine.
When working with async you should always return a Task. Otherwise it would be "fire and forget", and you have absolutely no way of interacting with the Task.
Therefore you should change the signature of SetIdentifier to return a Task, like this:
public async Task SetIdentifier(string identifier)
{
await SetContentAsync();
DoSomething();
}
Then you can wait for the operation to complete in the test:
[Test]
public async void Content_WhenModifierIsXXX_ReturnsSomeViewModel()
{
var viewModel = new EditorViewModel();
await viewModel.SetIdentifier("XXX");
Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>());
}
Or, if your test runner does not support async:
[Test]
public void Content_WhenModifierIsXXX_ReturnsSomeViewModel()
{
var viewModel = new EditorViewModel();
viewModel.SetIdentifier("XXX").Wait();
Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>());
}

Making interface implementations async

I’m currently trying to make my application using some Async methods.
All my IO is done through explicit implementations of an interface and I am a bit confused about how to make the operations async.
As I see things I have two options in the implementation:
interface IIO
{
void DoOperation();
}
OPTION1:
Do an implicit implementation async and await the result in the implicit implementation.
class IOImplementation : IIO
{
async void DoOperation()
{
await Task.Factory.StartNew(() =>
{
//WRITING A FILE OR SOME SUCH THINGAMAGIG
});
}
#region IIO Members
void IIO.DoOperation()
{
DoOperation();
}
#endregion
}
OPTION2:
Do the explicit implementation async and await the task from the implicit implementation.
class IOAsyncImplementation : IIO
{
private Task DoOperationAsync()
{
return new Task(() =>
{
//DO ALL THE HEAVY LIFTING!!!
});
}
#region IIOAsync Members
async void IIO.DoOperation()
{
await DoOperationAsync();
}
#endregion
}
Are one of these implementations better than the other or is there another way to go that I am not thinking of?
Neither of these options is correct. You're trying to implement a synchronous interface asynchronously. Don't do that. The problem is that when DoOperation() returns, the operation won't be complete yet. Worse, if an exception happens during the operation (which is very common with IO operations), the user won't have a chance to deal with that exception.
What you need to do is to modify the interface, so that it is asynchronous:
interface IIO
{
Task DoOperationAsync(); // note: no async here
}
class IOImplementation : IIO
{
public async Task DoOperationAsync()
{
// perform the operation here
}
}
This way, the user will see that the operation is async and they will be able to await it. This also pretty much forces the users of your code to switch to async, but that's unavoidable.
Also, I assume using StartNew() in your implementation is just an example, you shouldn't need that to implement asynchronous IO. (And new Task() is even worse, that won't even work, because you don't Start() the Task.)
Better solution is to introduce another interface for async operations. New interface must inherit from original interface.
Example:
interface IIO
{
void DoOperation();
}
interface IIOAsync : IIO
{
Task DoOperationAsync();
}
class ClsAsync : IIOAsync
{
public void DoOperation()
{
DoOperationAsync().GetAwaiter().GetResult();
}
public async Task DoOperationAsync()
{
//just an async code demo
await Task.Delay(1000);
}
}
class Program
{
static void Main(string[] args)
{
IIOAsync asAsync = new ClsAsync();
IIO asSync = asAsync;
Console.WriteLine(DateTime.Now.Second);
asAsync.DoOperation();
Console.WriteLine("After call to sync func using Async iface: {0}",
DateTime.Now.Second);
asAsync.DoOperationAsync().GetAwaiter().GetResult();
Console.WriteLine("After call to async func using Async iface: {0}",
DateTime.Now.Second);
asSync.DoOperation();
Console.WriteLine("After call to sync func using Sync iface: {0}",
DateTime.Now.Second);
Console.ReadKey(true);
}
}
P.S.
Redesign your async operations so they return Task instead of void, unless you really must return void.
I created a sample app based on Svick's answer and found that calling IOImplementation.DoOperationAsync() without the async keyword does not result in a compiler/Visual Studio warning. This was based on Visual Studio 2019 and .NET Core 3.1.
Sample code below.
public interface ISomething
{
Task DoSomethingAsync();
}
public class Something : ISomething
{
public async Task DoSomethingAsync()
{
await Task.Run(() => Thread.Sleep(2000));
Console.WriteLine("Message from DoSomethingAsync");
throw new Exception("Some exception");
}
}
class Program
{
static void Main(string[] args)
{
ISomething something = new Something();
Console.WriteLine("pre something.DoSomethingAsync() without await");
something.DoSomethingAsync(); // No compiler warning for missing "await" and exception is "swallowed"
Console.WriteLine("post something.DoSomethingAsync() without await");
Thread.Sleep(3000);
// Output:
// pre something.DoSomethingAsync() without await
// post something.DoSomethingAsync() without await
// Message from DoSomethingAsync
}
}
An abstract class can be used instead of an interface (in C# 7.3).
// Like interface
abstract class IIO
{
public virtual async Task<string> DoOperation(string Name)
{
throw new NotImplementedException(); // throwing exception
// return await Task.Run(() => { return ""; }); // or empty do
}
}
// Implementation
class IOImplementation : IIO
{
public override async Task<string> DoOperation(string Name)
{
return await await Task.Run(() =>
{
if(Name == "Spiderman")
return "ok";
return "cancel";
});
}
}

Categories