Reputation: 1504
I'd like to understand the TPL a little bit better. How would I for example write something to the screen until a task finishes. I can't call 'await' because I want the main thread to be notified instead of proactively calling 'await' and I don't want to stop execution until the task is finished.
Some example code:
var task = Task.Run(()=>
{
Task.Delay(10000);
});
while(true)
{
Console.WriteLine("Running...");
//I want to exit the loop the second 'task' finishes
//and print 'finished'
}
Upvotes: 0
Views: 10212
Reputation: 12629
You can achieve your goal using creating separate function to use in Task.Run and passing parameter by reference. Function should be something like below.
private void PerformTask(ref bool isComplete)
{
System.Threading.Thread.Sleep(5000);
isComplete = true;
}
Call above function from Task.Run
. Your current function should be like below.
bool isComplete = false;
System.Threading.Tasks.Task.Run(() => PerformTask(ref isComplete));
while (!isComplete)
{
Console.WriteLine("Running...");
System.Threading.Thread.Sleep(1000);
}
Upvotes: 1
Reputation: 10927
There are a a couple of ways you cam achieve this:
First you can use Lambda expression in Order to invoke your action, but look at the code:
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
Console.WriteLine("Application thread ID: {0}",
Thread.CurrentThread.ManagedThreadId);
var t = Task.Run(() => { Console.WriteLine("Task thread ID: {0}",
Thread.CurrentThread.ManagedThreadId);
} );
t.Wait();
}
}
// The example displays the following output:
// Application thread ID: 1
//
notice the t.Wait()
:
The call to the
Wait
method ensures that the task completes and displays its output before the application ends. Otherwise, it is possible that the Main method will complete before the task finishes.
So we understand that it's imperative to call the Wait()
method in order make sure that the task completes and displays its output.
You can use the second way also:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
var list = new ConcurrentBag<string>();
string[] dirNames = { ".", ".." };
List<Task> tasks = new List<Task>();
foreach (var dirName in dirNames) {
Task t = Task.Run( () => { foreach(var path in Directory.GetFiles(dirName))
list.Add(path); } );
tasks.Add(t);
}
Task.WaitAll(tasks.ToArray());
foreach (Task t in tasks)
Console.WriteLine("Task {0} Status: {1}", t.Id, t.Status);
Console.WriteLine("Number of files read: {0}", list.Count);
}
}
For more reference see Task.Run Method.
One highlight regarding your quesion:
taken from Asynchronous programming with async and await (C#):
An async method typically contains one or more occurrences of an
await
operator, but the absence of await expressions doesn’t cause a compiler error. If an async method doesn’t use anawait
operator to mark a suspension point, the method executes as a synchronous method does, despite the async modifier. The compiler issues a warning for such methods.
That implies that either way you will have to wait for your tasks to finish and the main thread will have to wait this way or another.
Upvotes: 2
Reputation: 1720
Try to do something like this:
var task = Task.Run(() =>
{
Task.Delay(10000).Wait();
});
bool terminate = false;
while (!task.GetAwaiter().IsCompleted && !terminate)
{
// do something
if (task.GetAwaiter().IsCompleted) break;
// do something heavy
if (task.GetAwaiter().IsCompleted) break;
// do another heavy operation
for (int i = 0; i < 10000; i++)
{
// it took too long!
if (i == 1000)
{
terminate = true;
break;
}
}
}
Upvotes: 0
Reputation: 472
The ContinueWith function is a method available on the task that allows executing code after the task has finished execution. In simple words it allows continuation.
Things to note here is that ContinueWith also returns one Task. That means you can attach ContinueWith one task returned by this method.
Task<string> t = Task.Run(() => LongRunningOperation("Continuewith", 500));
t.ContinueWith((t1) =>
{
Console.WriteLine("Running...");
});
Upvotes: 1