Win8 C# trouble with async/await - c#

Why in the second case the exception is thrown?
async void f() {
await media.InitializeAsync();
isInit = true;
capturePreview.Source = media;
await media.StartPreviewAsync(); // Ok
}
// ------------------------------------------
void f() {
StaticClass.g(capturePreview.Source);
}
public static class StaticClass {
public static async void g(MediaSource source) {
await media.InitializeAsync();
isInit = true;
source = media;
await media.StartPreviewAsync(); // Unknown Exception (It's seems that media isn't init)
}
}

The f() function use a function which include async.
So I think the f() should be signed async as well.
Like this: void async f(){...}

If you really want media to be initialized, why don't you do the rest of the code in the .done function ?
void f() {
StaticClass.g(capturePreview.Source);
}
public static class StaticClass {
public static async void g(MediaSource source) {
media.InitializeAsync().done(
isInit = true;
source = media;
await media.StartPreviewAsync(););
}
}
Even if I'm not fully sure you can do an async within a done callback.

Related

TaskCompletionSource - code stop executing when disposing

I am using the library to manage WiFi. The library has a method to scan networks based on events.
I wrap this library with my code and I want to change events to the async pattern.
So my method looks like this:
public Task ScanNetworksAsync()
{
var tcs = new TaskCompletionSource<bool>();
void Callback(Wlan.WlanNotificationData data)
{
switch (data.notificationCode)
{
case (int) Wlan.WlanNotificationCodeAcm.ScanFail:
_wlanInterface!.WlanNotification -= Callback;
tcs.SetResult(false);
break;
case (int) Wlan.WlanNotificationCodeAcm.ScanComplete:
_wlanInterface!.WlanNotification -= Callback;
tcs.SetResult(true);
break;
}
}
_wlanInterface!.WlanNotification += Callback;
try
{
_wlanInterface!.Scan();
}
catch (Exception e)
{
tcs.SetException(e);
}
return tcs.Task;
}
Important is it that implement Dispose method where I dispose internal client.
public void Dispose() => ((IDisposable) _internalClient).Dispose();
Place where I use my class:
internal class Program
{
private static IContainer? _container;
private static async Task Main(string[] args)
{
_container = new Startup().BuildContainer();
await using (var scope = _container!.BeginLifetimeScope())
{
var s = scope.Resolve<IWiFiClient>();
await s.ScanNetworksAsync();
}
SubscribeEvents();
}
}
And here I have a problem. Method SubscriveEvents never call.
When I change
await s.ScanNetworkAsync();
to
s.ScanNetworkAsync().GetWaiter().GetResult();
then everything works but I don't know why.
And everything all works when I use await but not implement dispose method.
I don't understand it because the task is completed before disposing scope, so why code is hanging?

Asynchronous method using delegates [duplicate]

This question already has an answer here:
async Task vs async void
(1 answer)
Closed 3 years ago.
How would I make the main thread wait until DisplayAdd has displayed the output? If I add a Console.Read() at the end, everything works but is there another way to tell the main thread to wait until Calculate() has finished?
namespace TestDelegate
{
public class Add
{
public delegate void SendResult(int i);
public SendResult WhereToSend;
public async void Calculate (int number)
{
Console.WriteLine("Entered");
int result = number + number;
await Task.Delay(4000);
WhereToSend (result);
// Console.Read();
}
}
}
namespace TestStuff
{
class Program
{
static void Main(string[] args)
{
Add obj = new Add();
Console.WriteLine("Started Calculating");
obj.Calculate(10);
obj.WhereToSend = DisplayAdd;
}
static void DisplayAdd(int value)
{
Console.WriteLine(value);
}
}
}
You can define the delegate as Task return type (awaitable type). With this the method will finish before main thread terminates.
namespace TestDelegate
{
public delegate Task SendResult(int i);
public class Add
{
public SendResult WhereToSend;
public async Task Calculate (int number)
{
Console.WriteLine("Entered");
int result = number + number;
await WhereToSend (result);
}
}
}
namespace TestStuff
{
class Program
{
static void Main(string[] args)
{
Add obj = new Add();
obj.WhereToSend = DisplayAdd;
Console.WriteLine("Started Calculating");
obj.Calculate(10).Wait();
}
static async Task DisplayAdd(int value)
{
// Some awaitable operation like below as per your business logic
await Task.Delay(1);
Console.WriteLine(value);
}
}
}
In above program, I've changed the definition of Calculate method to async Task so that it can be marked for Waitable. The async void method are primarily used for UI events hanlder or fire and forget method.
Please check this dotnetfiddle which demonstrates the scenario.

SendOrPostCallback behaviour

SendOrPostCallback Represents a method to be called when a message is to be dispatched to a synchronization context. In first case SendOrPostCallback points on async method that i guess should be executed synchronously. What will happen if Delegate will point on async delegate? How behaviour should change?
Before changes:
public class ViewModel
{
public ViewModel()
{
SynchronizationContext.Current.Post(new SendOrPostCallback(SomeMethods), null);
}
private async void SomeMethods(object obj)
{
await Foo(obj);
}
private async Task Foo(object obj)
{
bool Canceled = false;
while (!Canceled)
{
await Task.Delay(3000);
//...
}
}
}
After changes:
public class ViewModelImproved
{
public ViewModelImproved()
{
SynchronizationContext.Current.Post(new SendOrPostCallback(async (obj) => { await SomeMethods(obj); }), null);
}
private async Task SomeMethods(object obj)
{
await Foo(obj);
}
private async Task Foo(object obj)
{
bool Canceled = false;
while (!Canceled)
{
await Task.Delay(3000);
}
//...
}
}
There's no substantial difference. In the first code, there's an async void, and in the second code, there's an async void. In the second code, the async void is hidden within a lambda expression.
Generally, you should avoid async void. In this particular case, it may be OK, since you're dealing with a UI context.

Suggested pattern for gracefully restart cancelled async Tasks on non UI application

I have a console app that instantiates a WeatherClientManager class.
The main thread in the console app requests current weather status in the WeatherClientManager class, but the WeatherClientManager class continuously receives data from a server.
In code:
public static void Main(string [])
{
Program p = new Program();
Task.Run(()=>p.RunLoop());
}
class Program{
WeatherClientManager wcM;
public void RunLoop()
{
wcM = new WeatherClientManager ();
await wcM.InitiateConnection().ConfigureAwait(false);
}
}
class WeatherClientManager
{
public async Task<bool> InitiateConnection()
{
TCPClient tcpClient = new TcpClient(GetTCPDetailsFromConfig())
await tcpClient.ConnectAsync()
CancellationTokenSource cts = new CancellationTokenSource();
if(tcpClient.Connected)
{
Task.Run(()=>ReceiveTask(cts.Token));
Task.Run(()=>SendKeepAlive(cts.Token));
return true;
}
return false;
}
private void ReceiveTask(CancellationToken t)
{
try{
networkStream.Receive(..) // throws exception
}
catch(Exception e)
{
Stop(e);
}
}
private void SendKeepAlive(CancellationToken t)
{
while(!t.IsCancellationRequested)
{
try{
networkStream.Write(..) // throws exception
}
catch(Exception e)
{
Stop(e);
}
}
}
private void Stop(Exception e )
{
log.Error(e);
e.Cancel();
}
}
One of many crap ideas I have is:
Task.Run( () =>
{
while(true)
{
var t1 = Task.Run(()=>ReceiveTask(cts.Token));
var t2= Task.Run(()=>SendKeepAlive(cts.Token));
try{
Tasks.WhenAny(); // should block
}
catch(Exception e)
{
}
finally{
Cleanup();
InitiateConnections();
}
}
}
But I hate the idea of spinning a task to control two sub tasks. My problem is where and how to re-initiate the connection. Any ideas?
EDIT:
I've updated the code such that WeatherClientManager has a OnDisconnectDetected event. So the Program.cs class subscribes like so:
weatherServerManager.OnDisconnectDetected += HandleDisconnectDetection
public async void HandleDisconnectDetection()
{
wsM = new WeatherClientManager ();
wsM.InitiateConnection().ConfigureAwait(false);
}
private void SendKeepAlive(CancellationToken t)
{
while (...)
{
try{}
catch(Exception e)
{
OnDisconnectDetected?.Invoke();
}
}
}
When the handler is invoked by the WeatherClientManager it creates a new task that should continue in a different context. The KeepAlive task should exit then.
Still feels hacky but ideas welcome!
As a general rule, I prefer composition of methods over raising events. In particular, avoid the Task.Run-based fire-and-forget.
In the case of asynchronous sockets, I think it makes sense to give each socket a main loop:
class WeatherClientManager
{
public async Task MainLoop()
{
TCPClient tcpClient = new TcpClient(GetTCPDetailsFromConfig())
await tcpClient.ConnectAsync();
CancellationTokenSource cts = new CancellationTokenSource();
var receiveTask = Task.Run(()=>ReceiveTask(cts.Token));
var keepaliveTask = Task.Run(()=>SendKeepAlive(cts.Token));
await Task.WhenAll(receiveTask, keepaliveTask);
}
}
These can then be composed into the main program's main loop:
class Program
{
public async Task RunLoop()
{
while (true)
{
wcM = new WeatherClientManager();
await wcM.MainLoop();
}
}
}
which in turn is composed into Main:
public static void Main(string [])
{
Program p = new Program();
p.RunLoop().GetAwaiter().GetResult();
}
By avoiding fire-and-forget, you're ensuring that your code will always observe all exceptions. Ignoring tasks is occasionally okay but usually a mistake.

C# async method call

I would have a async call to a function as following:
I'll call a method from the main method, this function should be async, how I do this?
A little example:
private static void Main(string[] args)
{
StartDoingNothingAsync();
Console.WriteLine("test");
Console.Read();
}
private static async void StartDoingNothingAsync()
{
for (var i = 0; i < 5000; i++)
{
//do something
}
Console.WriteLine("leaved");
}
I would first the output "test", before "leaved", how can I practice this?
The simplest option would be to introduce a delay into your async method:
private static async void StartDoingNothingAsync()
{
await Task.Delay(1000);
// This will be called on a thread-pool thread
Console.WriteLine("leaved");
}
That won't guarantee that test will be printed before leaved, but it seems very likely. If you actually want a guarantee, you'd have to pass something into StartDoingNothingAsync that you then signal after printing test... but it's not really clear what you're trying to achieve.
Note that async methods should almost never be void - basically that's only available to allow for async event handlers. Make the method return Task instead - that way your calling code can tell when it's completed. (Even if you don't use that fact in this case, it's a good habit to get into.)
Now that we have a bit more information about what you're trying to achieve, I would recommend not making StartDoingNothingAsync an async method - just use a task instead:
private static void Main(string[] args)
{
Task task = Task.Run(DoSomething);
Console.WriteLine("test");
task.Wait();
Console.Read();
}
static void DoSomething()
{
// Code to run on a separate thread
}
You can do it like this
private static void Main(string[] args)
{
StartDoingNothingAsync();
Console.WriteLine("test");
Console.Read();
}
private static async void StartDoingNothingAsync()
{
await Task.Run(async delegate()
{
for (var i = 0; i < 5000; i++)
{
//do something
}
Console.WriteLine("leaved");
});
}
You can use Task for that. In that case you don't need to mark your function as async:
private static void Main(string[] args)
{
new Task(StartDoingNothing).Start();
Console.WriteLine("test");
Console.Read();
}
private static void StartDoingNothing()
{
for (var i = 0; i < 5000; i++)
{
//do something
}
Console.WriteLine("leaved");
}

Categories

Resources