Processing on shared variable by parallel tasks - c#

I am beginning with task library. I wrote simple code like
private void button1_Click(object sender, EventArgs e)
{
simpleMost();
}
string mesg;
void simpleMost()
{
mesg = "";
button1.Enabled = false;
Task t1 = new Task(delegate { makeResult(1); });
Task t2 = new Task(delegate { makeResult(2); });
Task t3 = new Task(delegate { makeResult(3); });
t1.Start();
t2.Start();
t3.Start();
t1.Wait();
t2.Wait();
t3.Wait();
richTextBox1.Text = mesg;
button1.Enabled = true;
}
void makeResult(int a)
{
mesg += "\nTask" + a;
}
I click my button1 again and again and get following outputs
1.
Task3
Task1
Task2
2.
Task1
Task2
Task3
3.
Task1
Task2
Task3
4.
Task2
Task3
5.
Task1
Task3
6.
Task1
Task2
In 4,5,6 cases why does not makeResult work correctly. When I checked the Task states after wait statements they are found all completed but one of them misses the correct execution of function passed to it

You have several tasks, each of which is modifying the same shared resource in a non-atomic way.
mesg += "\nTask" + a;
is effectively:
mesg = mesg + "\nTask" + a;
... so if one task reads mesg, then another task writes a new value to it, then the first task will concatenate the strings using the old value, and write that back to the variable.
The simplest way to avoid this would be to use locking, so that only one thread can execute the modification statement at a time. It's not as elegant as it might be, but it should remove the race condition you currently have.

I think sometimes 2 tasks trying to access to "mesg" at the same time. Try it with a lock.
object syncObject = new object();
void makeResult(int a)
{
lock (syncObject)
{
mesg += "\nTask" + a;
}
}

Related

Get clipboard text in async method

I have a problem getting clipboard text via the async method. Because it always returns an empty value (while it's not empty). This is a simple demonstration of the problem:
private async void button_Click(object sender, EventArgs e)
{
string result = await Task<string>.Run(() =>
{
System.Threading.Thread.Sleep(3000);
return Clipboard.GetText(); //returns empty! (but clipboard is not empty)
});
MessageBox.Show(result);
}
I'm sure that the clipboard is not empty. what's the solution?
It doesn't work because the clipboard only works when the COM threading model (apartment) is STA while your Task apartment is MTA.
You can't change the apartment of the Task, BUT you can use Thread instead. Thread has a SetApartmentState method.
STA and MTA explained here
But I've found a solution to create an STA Task !
The trick is to run an STA thread using a Task:
public static Task<T> StartSTATask<T>(Func<T> func)
{
var tcs = new TaskCompletionSource<T>();
var thread = new Thread(() =>
{
try
{
var result = func();
tcs.SetResult(result);
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task;
}
So now you can make it work like this:
private async void button1_Click(object sender, EventArgs e)
{
var result = await StartSTATask(() =>
{
Thread.Sleep(3000);
return Clipboard.GetText();
});
MessageBox.Show(result);
}
This should work:
private static int counter;
private async void button1_Click(object sender, EventArgs e)
{
counter++;
button1.Text = counter.ToString();
// Solution 1 (preferred)
await LongOperation();
Debug.WriteLine("Solution 1 completed for counter " + counter);
// Solution 2 (use if LongOperation is CPU-bound)
var t = Task.Run(LongOperation);
await t;
Debug.WriteLine("Solution 2 completed for counter " + counter);
Debug.WriteLine(Clipboard.GetText());
}
private async Task LongOperation()
{
await Task.Delay(10000);
}
Click 3 times in a row on button1. Result:
// Click 3 times in a row on the button. Result:
// After 10 seconds:
Solution 1 completed for counter 3
Solution 1 completed for counter 3
Solution 1 completed for counter 3
// After 10 more seconds:
Solution 2 completed for counter 3
<clipboard content>
Solution 2 completed for counter 3
<clipboard content>
Solution 2 completed for counter 3
<clipboard content>

Why TPL Dataflow block.LinkTo does not give any output?

I am quite new to the topic TPL Dataflow. In the book Concurrency in C# I tested the following example. I can't figure out why there's no output which should be 2*2-2=2;
static void Main(string[] args)
{
//Task tt = test();
Task tt = test1();
Console.ReadLine();
}
static async Task test1()
{
try
{
var multiplyBlock = new TransformBlock<int, int>(item =>
{
if (item == 1)
throw new InvalidOperationException("Blech.");
return item * 2;
});
var subtractBlock = new TransformBlock<int, int>(item => item - 2);
multiplyBlock.LinkTo(subtractBlock,
new DataflowLinkOptions { PropagateCompletion = true });
multiplyBlock.Post(2);
await subtractBlock.Completion;
int temp = subtractBlock.Receive();
Console.WriteLine(temp);
}
catch (AggregateException e)
{
// The exception is caught here.
foreach (var v in e.InnerExceptions)
{
Console.WriteLine(v.Message);
}
}
}
Update1: I tried another example. Still I did not use Block.Complete() but I thought when the first block's completed, the result is passed into the second block automatically.
private static async Task test3()
{
TransformManyBlock<int, int> tmb = new TransformManyBlock<int, int>((i) => { return new int[] {i, i + 1}; });
ActionBlock<int> ab = new ActionBlock<int>((i) => Console.WriteLine(i));
tmb.LinkTo(ab);
for (int i = 0; i < 4; i++)
{
tmb.Post(i);
}
//tmb.Complete();
await ab.Completion;
Console.WriteLine("Finished post");
}
This part of the code:
await subtractBlock.Completion;
int temp = subtractBlock.Receive();
is first (asynchronously) waiting for the subtraction block to complete, and then attempting to retrieve an output from the block.
There are two problems: the source block is never completed, and the code is attempting to retrieve output from a completed block. Once a block has completed, it will not produce any more data.
(I assume you're referring to the example in recipe 4.2, which will post 1, causing the exception, which completes the block in a faulted state).
So, you can fix this test by completing the source block (and the completion will propagate along the link to the subtractBlock automatically), and by reading the output before (asynchronously) waiting for subtractBlock to complete:
multiplyBlock.Complete();
int temp = subtractBlock.Receive();
await subtractBlock.Completion;

Is it possible to execute two async methods in parallel?

If I execute two tasks, I can execute the two tasks at the same time and wait until the two tasks are finished. With this code:
Task<bool> tsk01 = Task.Run(()=> my code; return true);
Task<bool> tsk02 = Task.Run(()=> my code; return true);
Task.WaitAll(tsk01, tsk02);
//next code
In this case the following code is only executed when all tasks are finished. But the application is not blocked.
However if I have this code:
private async void Button_Click_2(object sender, RoutedEventArgs e)
{
Task<bool> tsk01 = miMetodoAsync01();
Task<bool> tsk02 = miMetodoAsync02();
Task.WaitAll(tsk01, tsk02);
}
private async Task<bool> miMetodoAsync02()
{
return await TaskEx.Run<bool>(() =>
{
Int64 resultado = 0;
for (Int64 i = 1; i < 1000000000; i++)
{
resultado = resultado + 1;
}
return true;
}).ConfigureAwait(false);
}
private async Task<bool> miMetodoAsync01()
{
return await TaskEx.Run<bool>(() =>
{
Int64 resultado = 0;
for (Int64 i = 1; i < 1000000000; i++)
{
resultado = resultado + 1;
}
return true;
}).ConfigureAwait(false);
}
In this second option the application is blocked because the WaitAll seems to wait for a response from the tasks that never happens.
Why in the first case the application is not blocked and in the second one it is?
Both your examples will block the UI thread. That's what Task.WaitAll means.
However, you can use TaskEx.WhenAll:
await TaskEx.WhenAll(tsk01, tsk02);
The method Task.WaitAll will block the UI thread as it waits for all tasks to return before continuing.
The code examples that you gave for creating a Task are basically the same (albeit written slightly different ways). Both the return Task<bool>.
The difference is the function being run inside both of your lambda expressions. Your first example has a "my code" reference and returns. The second example you created two counters.
If your "my code" is defined differently than the the counters created in the second example, or if you are only returning true in your lambda expression, then you will get the appearance of one waiting over the other.
Simply returning true will end the threads immediately after they are created. Where-as the counter takes time to compute (also depending on your CPU speed).
If you add the same counter into your function of the first example, you will find that both take the same time, and Task.WaitAllblocks your UI. You can use the System.Diagnositics.StopWatch class to time it.
static void Main(string[] args)
{
string test = Console.ReadLine();
System.Diagnostics.Stopwatch t = new System.Diagnostics.Stopwatch();
t.Start();
Task<bool> task1 = Task.Run<bool>(() => { return true; });
Task<bool> task2 = Task.Run<bool>(() => { return true; });
Task.WaitAll(task1, task2);
t.Stop();
Console.WriteLine("Elapsed time: " + t.Elapsed);
System.Diagnostics.Stopwatch t2 = new System.Diagnostics.Stopwatch();
t2.Start();
Task<bool> task3 = asyncMethod1();
Task<bool> task4 = asyncMethod2();
Task.WaitAll(task3, task4);
t2.Stop();
Console.WriteLine("Elapsed time: " + t2.Elapsed);
Console.Read();
}

How to append the return value to single complex variable from 3 threads in c#?

I am calling 3 different functions in 3 threads and I need to append the all the return values from 3 threads.
what I tried was
Thread t1 = new Thread(() => response.Candidate = AddCandidate2Daxtra(request, args));
t1.Start();
Thread t2 = new Thread(() => response.Candidate.HRXML = parsecv(profile));
t2.Start();
Thread t3 = new Thread(() => response.Candidate.Attachments.Add(Print2Flash(alias, bytes, args)));
t3.Start();
while (t1.IsAlive == true || t2.IsAlive == true || t3.IsAlive == true)
{
Thread.Sleep(1000);
}
but finally I'm getting first thread value only.I'm not getting the remaining two threads values.
So any one please help me what is the problem?
Thanks In advance.
You have a race condition because you don't know the order in which the threads will finish.
Use a separate local variable for each thread, which you assign inside the thread constructor similar to how you do just now with response.
Then wait for all the threads using .Join():
t1.Join();
t2.Join();
t3.Join();
Then use the local variables to set response after all the Join() calls have returned.
However, I'd use Tasks instead. Here's an example. It runs in separate threads three different methods each of which has a different return type:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Demo
{
class Program
{
private void run()
{
// Using tasks directly:
var task1 = Task<int>.Factory.StartNew(methodOne);
var task2 = Task<string>.Factory.StartNew(methodTwo);
var task3 = Task<double>.Factory.StartNew(methodThree);
// Alternatively:
// var task1 = Task.Run(new Func<int>(methodOne));
// var task2 = Task.Run(new Func<string>(methodTwo));
// var task3 = Task.Run(new Func<double>(methodThree));
string result = string.Format
(
"Task 1: {0}, Task 2: {1}, Task 3: {2}",
task1.Result, // Accessing Task.Result automatically
task2.Result, // waits for the task to complete.
task3.Result
);
Console.WriteLine(result);
// Alternatively, you can use tasks indirectly via Parallel.Invoke().
// You might find this more readable and less typing:
int r1 = 0;
string r2 = null;
double r3 = 0;
Parallel.Invoke
(
() => r1 = methodOne(),
() => r2 = methodTwo(),
() => r3 = methodThree()
);
result = string.Format
(
"Task 1: {0}, Task 2: {1}, Task 3: {2}",
r1,
r2,
r3
);
Console.WriteLine(result);
}
static int methodOne()
{
Thread.Sleep(1000);
return 1;
}
static string methodTwo()
{
Thread.Sleep(750);
return "two";
}
static double methodThree()
{
Thread.Sleep(500);
return 3.0;
}
static void Main(string[] args)
{
new Program().run();
}
}
}
Whichever approach you take, the important thing is that you should not assign the results directly to response inside the thread or task - wait until all the threads or tasks have finished and only then assign the results to response.
This happens because the thread t1 is scheduled after t2 and t3. You can rewrite your code like this:
Thread t1 = new Thread(() => response.Candidate = AddCandidate2Daxtra(request, args));
t1.Start();
t1.Join();
Thread t2 = new Thread(() => response.Candidate.HRXML = parsecv(profile));
t2.Start();
Thread t3 = new Thread(() => response.Candidate.Attachments.Add(Print2Flash(alias, bytes, args)));
t3.Start();
while (/*t1.IsAlive == true || */t2.IsAlive == true || t3.IsAlive == true)
{
Thread.Sleep(1000);
}
You can do this:
// get all the data you need separately
Candidate candidate = null; // no idea of the real type
Thread t1 = new Thread(() => candidate = AddCandidate2Daxtra(request, args));
t1.Start();
HRXML HRXML = null; // no idea of the real type
Thread t2 = new Thread(() => HRXML = parsecv(profile));
t2.Start();
Attachment att = null; // no idea of the real type
Thread t3 = new Thread(() => att = Print2Flash(alias, bytes, args));
t3.Start();
while (t1.IsAlive || t2.IsAlive || t3.IsAlive)
{
Thread.Sleep(1000);
}
And when all is done:
response.Candidate = candidate;
candidate.HRXML = HRXML;
response.Candidate.Attachments.Add(att);
The problem may be that t2 and t3 are dependent on t1 completing. If t2 and t3 finish before t1 then their results will be injected into the older instance of Candidate. You need to break this dependency.
Consider the following code.
var t2 = Task.Factory.StartNew(() => parsecv(profile));
var t3 = Task.Factory.StartNew(() => Print2Flash(alias, bytes, args));
response.Candidate = AddCandidate2Daxtra(request, args);
response.Candidate.HRXML = t2.Result;
response.Candidate.Attachments.Add(t3.Result);
What we are doing here is launching t2 and t3 asynchronously and when they are complete their return values will be stored in the Task instances that are created. In the meantime, what was originally t1 will now be executed synchronously on the main thread. There is no point in creating a new thread to do this work. Just have the main the thread do it because otherwise it would be sitting their idle anyway. Once AddCandidate2Daxtra is complete then its constituent values can be retrieved from Task.Result and assigned. The Task.Result property blocks until the task completes.
There are various other ways to do this, but most will not be as elegant and easy to read as the above. If Task is not available to you then let me know in the comments and I will update my answer to include a non-TPL friendly method.

Create multiple threads and wait for all of them to complete

How can I create multiple threads and wait for all of them to complete?
It depends which version of the .NET Framework you are using. .NET 4.0 made thread management a whole lot easier using Tasks:
class Program
{
static void Main(string[] args)
{
Task task1 = Task.Factory.StartNew(() => doStuff());
Task task2 = Task.Factory.StartNew(() => doStuff());
Task task3 = Task.Factory.StartNew(() => doStuff());
Task.WaitAll(task1, task2, task3);
Console.WriteLine("All threads complete");
}
static void doStuff()
{
//do stuff here
}
}
In previous versions of .NET you could use the BackgroundWorker object, use ThreadPool.QueueUserWorkItem(), or create your threads manually and use Thread.Join() to wait for them to complete:
static void Main(string[] args)
{
Thread t1 = new Thread(doStuff);
t1.Start();
Thread t2 = new Thread(doStuff);
t2.Start();
Thread t3 = new Thread(doStuff);
t3.Start();
t1.Join();
t2.Join();
t3.Join();
Console.WriteLine("All threads complete");
}
I think you need WaitHandler.WaitAll. Here is an example:
public static void Main(string[] args)
{
int numOfThreads = 10;
WaitHandle[] waitHandles = new WaitHandle[numOfThreads];
for (int i = 0; i < numOfThreads; i++)
{
var j = i;
// Or you can use AutoResetEvent/ManualResetEvent
var handle = new EventWaitHandle(false, EventResetMode.ManualReset);
var thread = new Thread(() =>
{
Thread.Sleep(j * 1000);
Console.WriteLine("Thread{0} exits", j);
handle.Set();
});
waitHandles[j] = handle;
thread.Start();
}
WaitHandle.WaitAll(waitHandles);
Console.WriteLine("Main thread exits");
Console.Read();
}
FCL has a few more convenient functions.
(1) Task.WaitAll, as well as its overloads, when you want to do some tasks in parallel (and with no return values).
var tasks = new[]
{
Task.Factory.StartNew(() => DoSomething1()),
Task.Factory.StartNew(() => DoSomething2()),
Task.Factory.StartNew(() => DoSomething3())
};
Task.WaitAll(tasks);
(2) Task.WhenAll when you want to do some tasks with return values. It performs the operations and puts the results in an array. It's thread-safe, and you don't need to using a thread-safe container and implement the add operation yourself.
var tasks = new[]
{
Task.Factory.StartNew(() => GetSomething1()),
Task.Factory.StartNew(() => GetSomething2()),
Task.Factory.StartNew(() => GetSomething3())
};
var things = Task.WhenAll(tasks);
I've made a very simple extension method to wait for all threads of a collection:
using System.Collections.Generic;
using System.Threading;
namespace Extensions {
public static class ThreadExtension {
public static void WaitAll (this IEnumerable<Thread> threads) {
if (threads != null) {
foreach (Thread thread in threads) {
thread.Join();
}
}
}
}
}
Then you simply call:
List<Thread> threads = new List<Thread>();
// Add your threads to this collection
threads.WaitAll();
In .NET 4.0, you can use the Task Parallel Library.
In earlier versions, you can create a list of Thread objects in a loop, calling Start on each one, and then make another loop and call Join on each one.
If you don't want to use the Task class (for instance, in .NET 3.5), you can just start all your threads, and then add them to the list and join them in a foreach loop.
Example:
List<Thread> threads = new List<Thread>();
// Start threads
for (int i = 0; i < 10; i++) {
int tmp = i; // Copy value for closure
Thread t = new Thread(() => Console.WriteLine(tmp));
t.Start();
threads.Add(t);
}
// Join threads (wait threads)
foreach (Thread thread in threads) {
thread.Join();
}
I don't know if there is a better way, but the following describes how I did it with a counter and background worker thread.
private object _lock = new object();
private int _runningThreads = 0;
private int Counter{
get{
lock(_lock)
return _runningThreads;
}
set{
lock(_lock)
_runningThreads = value;
}
}
Now whenever you create a worker thread, increment the counter:
var t = new BackgroundWorker();
// Add RunWorkerCompleted handler
// Start thread
Counter++;
In work completed, decrement the counter:
private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Counter--;
}
Now you can check for the counter anytime to see if any thread is running:
if(Couonter>0){
// Some thread is yet to finish.
}
Most proposed answers don't take into account a time-out interval, which is very important to prevent a possible deadlock. Next is my sample code. (Note that I'm primarily a Win32 developer, and that's how I'd do it there.)
//'arrRunningThreads' = List<Thread>
//Wait for all threads
const int knmsMaxWait = 3 * 1000; //3 sec timeout
int nmsBeginTicks = Environment.TickCount;
foreach(Thread thrd in arrRunningThreads)
{
//See time left
int nmsElapsed = Environment.TickCount - nmsBeginTicks;
int nmsRemain = knmsMaxWait - nmsElapsed;
if(nmsRemain < 0)
nmsRemain = 0;
//Then wait for thread to exit
if(!thrd.Join(nmsRemain))
{
//It didn't exit in time, terminate it
thrd.Abort();
//Issue a debugger warning
Debug.Assert(false, "Terminated thread");
}
}
In my case, I could not instantiate my objects on the the thread pool with Task.Run() or Task.Factory.StartNew(). They would not synchronize my long running delegates correctly.
I needed the delegates to run asynchronously, pausing my main thread for their collective completion. The Thread.Join() would not work since I wanted to wait for collective completion in the middle of the parent thread, not at the end.
With the Task.Run() or Task.Factory.StartNew(), either all the child threads blocked each other or the parent thread would not be blocked, ... I couldn't figure out how to go with async delegates because of the re-serialization of the await syntax.
Here is my solution using Threads instead of Tasks:
using (EventWaitHandle wh = new EventWaitHandle(false, EventResetMode.ManualReset))
{
int outdex = mediaServerMinConnections - 1;
for (int i = 0; i < mediaServerMinConnections; i++)
{
new Thread(() =>
{
sshPool.Enqueue(new SshHandler());
if (Interlocked.Decrement(ref outdex) < 1)
wh.Set();
}).Start();
}
wh.WaitOne();
}

Categories