I have such a function:
public async Task<bool> DoSomething()
{
var tcs = new TaskCompletionSource<bool>();
// Here is the problem. I need to keep this line because I wait on something asynchronously, but the function must return bool and I can't just return tcs.Task
while(something)
await Task.Delay(100);
someobject.somevent += () => {
// do some sht
tcs.SetResult(true);
}
// it doesn't work
return tcs.Task;
}
It's just a fake code but I have real situation where I need this. I want to keep DoSomething asynchronous but I also want to keep Task.Delay/Sleep in it. How do I do this in not-async function returning just Task?
UPDATE:
THIS WORKS:
class Program
{
static TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
static Task<bool> Test()
{
// tcs = new TaskCompletionSource<bool>();
Task.Factory.StartNew(() =>
{
Console.WriteLine("Waiting...");
Thread.Sleep(5000);
Console.WriteLine("Setting result");
if(tcs.TrySetResult(true))
Console.WriteLine("Result has been set");
});
return tcs.Task;
}
static async Task Test2()
{
Console.WriteLine("Starting awaiting");
var result = await Test();
Console.WriteLine(result.ToString());
}
static void Main(string[] args)
{
Test2();
Console.ReadKey(false);
}
}
and this doesn't
static async Task<bool> Test()
{
// tcs = new TaskCompletionSource<bool>();
Task.Factory.StartNew(() =>
{
Console.WriteLine("Waiting...");
Thread.Sleep(5000);
Console.WriteLine("Setting result");
if(tcs.TrySetResult(true))
Console.WriteLine("Result has been set");
});
return await tcs.Task;
}
what's worse, I have tested it in my windows forms app and awaiting tcs.Task caused weird crash coming from System.Threading....dll
Run turns something synchronous into a Task (by running it on a separate thread), TaskCompletionSource turns something that is already asynchronous into a Task . "If it is already asynchronous, why does it need to be turned into a Task ?"
Is it safe to pass non-thread-safe objects created on one thread to another using TaskCompletionSource. SetResult()? Yes, as long as the object can be used on a different thread than the one it was created on (of course).
An async keyword is a method that performs asynchronous tasks such as fetching data from a database, reading a file, etc, they can be marked as “async”. Whereas await keyword making “await” to a statement means suspending the execution of the async method it is residing in until the asynchronous task completes.
To start a task in C#, follow any of the below given ways. Use a delegate to start a task. Task t = new Task(delegate { PrintMessage(); }); t. Start();
If I understand correctly (it's tricky because your question isn't that easy to follow) you can restate things as follows:
public async Task<bool> DoSomething()
{
var tcs = new TaskCompletionSource<bool>();
someobject.somevent += () => {
// do some sht
tcs.SetResult(true);
}
return await tcs.Task;
}
The whole thing will come out a lot more elegantly if you separate out the logic of turning the event firing into a Task
into its own method.
public static Task<bool> WhenSomeEvent(this SomeObject someobject)
{
var tcs = new TaskCompletionSource<bool>();
Action handler = null;
handler = () =>
{
tcs.SetResult(true);
someobject.SomeEvent -= handler;
};
someobject.SomeEvent += handler;
return tcs.Task;
}
This allows you to write the business logic separately, without mixing in all of the logic of translating the event into a Task
:
public async Task<bool> DoSomething()
{
while(something)
await Task.Delay(100);
return await someobject.WhenSomeEvent();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With