-3

I have code like this

public async Task DoStuff()
{
    _client.Ready += () => client_Ready("test");

    await Task.Delay(-1);
}

private async Task client_Ready(string message)
{
    await _client.SendMessageAsync(message);
}

how can I say that after client_Ready being invoked once the whole DoStuff has to end/perform return instead of waiting?

Is there a "nice" way of doing it or I have to do some work around like throwing an Exception and catching it "above"?

MRE:

using System;
using System.Threading.Tasks;

public class Program
{
    public static async Task RandomlyDelayedStuff()
    {
        Console.WriteLine("this ended");
        await Task.Delay(200);
    }

    public static async Task DoStuff()
    {
        var rnd = new Random();

        await Task.Delay(rnd.Next(0, 5000)).ContinueWith(async task =>
        {
            await RandomlyDelayedStuff();
        });

        await Task.Delay(-1);
    }
    public static async Task Main()
    {
        await DoStuff();
        Console.WriteLine("ended");
    }
}
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Axelly
  • 589
  • 3
  • 7
  • 26
  • I don't understand what your `await Task.Delay(-1);` is supposed to achieve. What happens if you simply remove it? – Pac0 Dec 20 '20 at 23:55
  • I don't understand the question. Are you saying "I don't want `DoStuff` to return until `client_Ready` has finished executing"? If so - **why** do you want this? – mjwills Dec 20 '20 at 23:56
  • 1
    Please share a [mcve]. – mjwills Dec 20 '20 at 23:57
  • @mjwills I'm connecting to the `client` which after some time `X` returns answer to me and invokes `Ready` (`client_Ready` method). I used `Task.Delay(-1)` so the program doesn't exit `DoStuff` function instantly (before I received `Ready`). The problem is, that it never leaves it even after the event was invoked – Axelly Dec 20 '20 at 23:57
  • Yes, please provide MRE, because this part of needing to "doesn't exit `DoStuff`" doesn't make sense to me. You assigned an event handler, you just need the handler to be invoked, I don't understand why it's a problem that `DoStuff` immediately ends. – Pac0 Dec 21 '20 at 00:01
  • You’re creating a task, and asking it to wait indefinitely.. did you mean to apply this to the task returned by `client_Ready` which right now you’re ignoring? – stuartd Dec 21 '20 at 00:01
  • You likely want to use a TaskCompletionSource here https://dotnetfiddle.net/gnfH5C – TheGeneral Dec 21 '20 at 00:09

2 Answers2

2

Use a cancellation token. Pass the token to the delay call. You can create a CancellationTokenSource and call cancel on it, which will initiate a cancel call on the token.

CancellationTokenSource cancelTokenSource = new CancellationTokenSource();

public async Task DoStuff()
{
    _client.Ready += () => client_Ready("test");

    await Task.Delay(-1, cancelTokenSource.Token);

    // do something else here if desired
}

private async Task client_Ready(string message)
{
    await _client.SendMessageAsync(message);
    cancelTokenSource.Cancel();
}
jjxtra
  • 20,415
  • 16
  • 100
  • 140
0

You should be able to accomplish this via a Cancellation Token.

Code is untested, I've done it with a delay, and using cancel to reset, but never with an infinite timer and a cancel.

const int cDelayMS = -1;
private System.Threading.CancellationTokenSource mCancel = new();

DoStuff()
{
    Task.Delay(cDelayMS, mCancel.Token).ContinueWith(
                async antecedent =>
                {
                    if (antecedent.Status == TaskStatus.Canceled)
                    {
                        // do whatever here
                    }
                });
}