MultiThreading Async - c#

Why does this code not reach the Console.WriteLine("Other thread is done!"); ? This code is from Pro C# 5.0 and the .NET 4.5 Framework book, pg 717-718.
private static AutoResetEvent waitHandle = new AutoResetEvent(false);
static void Main(string[] args)
{
Console.WriteLine("ID of thread in Main(): {0}", Thread.CurrentThread.ManagedThreadId);
AddParms data = new AddParms(3, 4);
Thread t = new Thread(new ParameterizedThreadStart(Add));
t.Start(data);
waitHandle.WaitOne();
Console.WriteLine("Other thread is done!");
Console.ReadLine();
}
private static void Add(object data)
{
Console.WriteLine("ID of thread in Add(): {0}", Thread.CurrentThread.ManagedThreadId);
AddParms ap = (AddParms)data;
Console.WriteLine("{0} + {1} = {2}", ap.A, ap.B, ap.A + ap.B);
}

waitHandle.WaitOne();
This line causes the execution to stop until the wait handle is set.
The provided code never sets that wait handle, and thus the code blocks indefinitely.

Related

Call a Method from thread1 to thread2?

First: What I want to do?
I want to run multiple jobs on one thread, for example, I want to make a thread for calculations and always run methods inside of that.
Get a pointer like SynchronizationContext.Current or Thread.CurrentThread to access current job working.
3.A Cross-Platform way like Net Standard.
Second: Example-1 (CrossPlatform-Working) My example not working, because Post and Send method in SynchronizationContext don't work
class Program
{
static void Main(string[] args)
{
SynchronizationContext contextThread1 = null;
SynchronizationContext contextThread2 = null;
Thread thread1, thread2 = null;
thread1 = new Thread(() =>
{
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
contextThread1 = SynchronizationContext.Current;
while (true)
{
Thread.Sleep(1000);
if (contextThread2 != null)
{
contextThread2.Post((state) =>
{
//Thread.CurrentThread == thread2 always false because the method is not runnig from thread 2
Console.WriteLine("call a method from thread 1 for thread 2 :" + (Thread.CurrentThread == thread2));
}, null);
}
}
});
thread1.IsBackground = true;
thread1.Start();
thread2 = new Thread(() =>
{
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
contextThread2 = SynchronizationContext.Current;
while (true)
{
Thread.Sleep(1000);
if (contextThread1 != null)
{
contextThread1.Post((state) =>
{
//Thread.CurrentThread == thread1 always false because the method is not runnig from thread 1
Console.WriteLine("call a method from thread 2 for thread 1 :"+(Thread.CurrentThread == thread1));
}, null);
}
}
});
thread2.IsBackground = true;
thread2.Start();
Console.ReadKey();
}
}
Example-2: (No Cross PLatform because Windowsbase.dll): this example works fine but this is not cross platform.
class Program
{
static void Main(string[] args)
{
Dispatcher contextThread1 = null;
Dispatcher contextThread2 = null;
Thread thread1, thread2 = null;
thread1 = new Thread(() =>
{
contextThread1 = Dispatcher.CurrentDispatcher;
Dispatcher.Run();
});
thread1.IsBackground = true;
thread1.Start();
thread2 = new Thread(() =>
{
contextThread2 = Dispatcher.CurrentDispatcher;
Dispatcher.Run();
});
thread2.IsBackground = true;
thread2.Start();
while (true)
{
Thread.Sleep(1000);
if (contextThread2 != null)
{
contextThread2.Invoke(new Action(() =>
{
//Thread.CurrentThread == thread2 always false because the method is not runnig from thread 2
Console.WriteLine("call a method from thread 1 for thread 2 :" + (Thread.CurrentThread == thread2));
}));
}
if (contextThread1 != null)
{
contextThread1.Invoke(new Action(() =>
{
Console.WriteLine("call a method from thread 2 for thread 1 :" + (Thread.CurrentThread == thread1));
}));
}
}
Console.ReadKey();
}
}
You should always use a tool these days to make your life easier where possible. In this case you should use Microsoft's Reactive Framework. Just NuGet "System.Reactive" and add using System.Reactive.Linq;.
Then you can do this:
void Main()
{
var thread1 = new EventLoopScheduler();
var thread2 = new EventLoopScheduler();
Action action = () => Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
action();
thread1.Schedule(action);
Thread.Sleep(1000);
thread2.Schedule(action);
Thread.Sleep(1000);
thread2.Schedule(() =>
{
action();
thread1.Schedule(action);
});
Thread.Sleep(1000);
action();
}
The kind of output I get is:
11
12
14
14
12
11
If you follow along with the code you can see it is correctly scheduling to each thread.
When you want to shut down just call .Dispose() on each EventLoopScheduler.

Wait for RunOnUIThread to finish and continue executing the rest of the task

im developing an app for android via c#(xamarin.visual studio) , the problem is that i have some task to do that running in other threads , and when it should update the layout it should call Activity.RunOnUIThread , everything it's working well but the thread dont wait this method to finnish and continue executing the rest withuout waiting.
The question is : How to wait for RunOnUIThread to finish and after that continue executing rest of the commands of the task. ?
public void start(int threadCounter)
{
for (int i = 0; i < threadCounter; i++)
{
Thread thread1 = new Thread(new ThreadStart(RunScanTcp));
thread1.Start();
}
}
public void RunScanTcp()
{
int port;
//while there are more ports to scan
while ((port = portList.NextPort()) != -1)
{
count = port;
Thread.Sleep(1000); //lets be a good citizen to the cpu
Console.WriteLine("Current Port Count : " + count.ToString());
try
{
Connect(host, port, tcpTimeout);
}
catch
{
continue;
}
Activity.RunOnUiThread(() =>
{
mdata.Add(new data() { titulli = "Port : " + port, sekuenca = "Sequence : ", ttl = "Connection Sucessfull !", madhesia = "", koha = "Time : " });
mAdapter.NotifyItemInserted(mdata.Count() - 1);
if (ndaluar == false)
{
mRecyclerView.ScrollToPosition(mdata.Count() - 1);
}
}); // in that point i want to wait this to finish and than continue below...
Console.WriteLine("TCP Port {0} is open ", port);
}
First of all you should avoid creating new Threads.
In you case you must use ThreadPool.QueueUserWorkItem to enqueue the CPU bound operation.
Then you could use a ManualResetEventSlim or TaskCompletionSource to synchronize the the UI thread and the Worker Thread.
Example:
// mre is used to block and release threads manually. It is
// created in the unsignaled state.
ManualResetEventSlim mre = new ManualResetEventSlim(false);
RunOnUiThread(() =>
{
// Update UI here.
// Release Manual reset event.
mre.Set();
});
// Wait until UI operations end.
mre.Wait();
In your specific case:
for (int i = 0; i < threadCounter; i++)
{
ThreadPool.QueueUserWorkItem(RunScanTcp);
}
private void RunScanTcp(object stateInfo)
{
// Do CPU bound operation here.
var a = 100;
while (--a != 0)
{
// mre is used to block and release threads manually. It is
// created in the unsignaled state.
ManualResetEventSlim mre = new ManualResetEventSlim(false);
Activity.RunOnUiThread(() =>
{
// Update UI here.
// Release Manual reset event.
mre.Set();
});
// Wait until UI operation ends.
mre.WaitOne();
}
}
If you prefer to use TaskCompletionSource you could use an alternative approach:
private async void RunScanTcp(object stateInfo)
{
// Do CPU bound operation here.
var a = 100;
while (--a != 0)
{
// using TaskCompletionSource
var tcs = new TaskCompletionSource<bool>();
RunOnUiThread(() =>
{
// Update UI here.
// Set result
tcs.TrySetResult(true);
});
// Wait until UI operationds.
tcs.Task.Wait();
}
}
You could use Monitor.Wait and Monitor.Pulse with a shared myLock object to wait for the UI execution.
Activity.RunOnUiThread(() =>
{
mdata.Add(new data() { titulli = "Port : " + port, sekuenca = "Sequence : ", ttl = "Connection Sucessfull !", madhesia = "", koha = "Time : " });
mAdapter.NotifyItemInserted(mdata.Count() - 1);
if (ndaluar == false)
{
mRecyclerView.ScrollToPosition(mdata.Count() - 1);
}
lock(myLock) Monitor.Pulse(myLock)
});
lock(myLock) Monitor.Wait(myLock)
Console.WriteLine("TCP Port {0} is open ", port);
For those interested in an async/await solution, there is Stephen Cleary's AsyncManualResetEvent, e.g.:
var mre = new AsyncManualResetEvent();
this.context.RunOnUiThread(() =>
{
// Do awesome UI stuff
mre.Set();
});
await mre.WaitAsync();

The .Join() calling is never unblocked same when thread is terminated

I stop a thread execution with .Abort() and .Join() for wait the thread terminates. But the problem is that .Join() never unblock application, same when thread was terminated. Why? my code:
th.Abort();
Console.WriteLine("request sent, please wait..");
th.Join();
Console.WriteLine("done!");
the above code never unlock application, but it works fine:
th.Abort();
Console.WriteLine("request sent, please wait..");
while (serverTh.ThreadState != ThreadState.Aborted) {
Thread.Sleep(500);
}
Console.WriteLine("done!");
Thanks in advance.
What's going on in the thread that you are trying to abort? For instance, this works fine:
public static void Main(String[] args)
{
var t = new Thread(LoopForever);
t.Start();
Thread.Sleep(500);
Console.WriteLine("request sent, please wait..");
t.Abort();
t.Join();
Console.WriteLine("done!");
Console.ReadLine();
}
public static void LoopForever()
{
Console.WriteLine("Running!");
while (true)
{
Thread.Sleep(100);
Console.WriteLine("Running!");
}
}
The only thing that comes to mind is maybe your background thread is catching the AbortException and then calling ResetAbort on itself:
public static void Main(String[] args)
{
var t = new Thread(LoopForever);
t.Start();
// Let the thread get started...
Thread.Sleep(500);
Console.WriteLine("request sent, please wait..");
t.Abort();
t.Join();
Console.WriteLine("done!");
Console.ReadLine();
}
public static void LoopForever()
{
Console.WriteLine("Running!");
while (true)
{
try
{
Console.WriteLine("Running!");
Thread.Sleep(100);
}
catch (ThreadAbortException ex)
{
Console.WriteLine("Alas, I was aborted!");
Thread.ResetAbort();
Console.WriteLine("But behold, I live!");
}
}
}

UI updates using BeginInvoke hung until thread completes?

I have 1 class (acBL) which handles 2 threads (fpDoWork). Any work that is done in fpDoWork will trigger an event back to the acBL class. On my form I declare the acBL class and associate Event handlers on acBL - this way whenever the event is called, it 'should' update the UI with changes.
What is not happening is, when each fpDoWork thread is started, it performs the operations, the ProcessingEvent is called and does go into the frmMain.handlerProcessing1 event. It gets to the point where this.BeginInvoke(new Processing2Event (handlerProcessing2), status) is called, then it just hangs and waits until the thread has finished its work before continuing to update the UI. I tried this.Invoke, but that method just seems to hang. Any ideas?
Code inside frmMain
Earlier in the code:
this.acBL.Processing1Event += new acBL.Processing1(handlerProcessing1);
this.acBL.Processing2Event += new acBL.Processing2(handlerProcessing2);
Handlers:
private void handlerProcessing1(string status) {
if (InvokeRequired) {
this.BeginInvoke(new MethodInvoker(this.Refresh));
this.BeginInvoke(new Processing1Event (handlerProcessing1), status);
}
else {
Console.WriteLine("UPDATING 1: "+status);
lblForProcessing1.Text = status;
this.Refresh();
return;
}
}
private void handlerProcessing2(string status) {
if (InvokeRequired) {
this.BeginInvoke(new MethodInvoker(this.Refresh));
this.BeginInvoke(new Processing2Event (handlerProcessing2), status);
}
else {
Console.WriteLine("UPDATING 2: "+status);
lblForProcessing2.Text = status;
this.Refresh();
return;
}
}
Code inside acBL
In a main method:
bool thread1Complete = false;
fpDoWork fpDoWork1 = new fpDoWork();
fpDoWork1.GUIForm = frmMain;
fpDoWork1.ProcessingEvent += new fpDoWork.Processing(handlerProcessing1Event);
fpDoWork1.ThreadCompleteEvent += new fpDoWork.ThreadComplete(thread1Complete);
Thread fpDoWork1Thread= new Thread(new ThreadStart(fpDoWork1.StartWork));
bool thread2Complete = false;
fpDoWork fpDoWork2 = new fpDoWork();
fpDoWork2.GUIForm = frmMain;
fpDoWork2.ProcessingEvent += new fpDoWork.Processing(handlerProcessing2Event);
fpDoWork2.ThreadCompleteEvent += new fpDoWork.ThreadComplete(thread2Complete);
Thread fpDoWork2Thread= new Thread(new ThreadStart(fpDoWork2.StartWork));
Console.WriteLine("Work for 1 Thread started...");
fpDoWork1Thread.Start();
Console.WriteLine("Work for 2 Thread started...");
fpDoWork2Thread.Start();
while (!thread1Complete && !thread2Complete ) {
if (!thread1Complete && !thread2Complete ) {
Console.WriteLine("Waiting for both copying threads...");
}
else if (!thread1Complete && thread2Complete ) {
Console.WriteLine("Waiting for thread 1...");
}
else if (thread1Complete && !thread2Complete ) {
Console.WriteLine("Waiting for thread 2...");
}
Thread.Sleep(1000);
}
Console.WriteLine("All done");
Else where in the code:
public delegate void ProcessingFor1 (string filename);
public delegate void ProcessingFor2 (string filename);
public event ProcessingFor1 ProcessingEventFor1;
public event ProcessingFor2 ProcessingEventFor2;
private void handlerProcessing1Event(string filename) {
Console.WriteLine("Processing 1: " + filename);
ProcessingEventFor1(filename);
}
private void handlerProcessing1Event(string filename) {
Console.WriteLine("Processing 2: " + filename);
ProcessingEventFor2(filename);
}
the reason your UI is not updating is that the primary UI thread is stuck in your while() loop. BackgroundWorker is your friend
try to avoid creating threads in one thread and sit there waiting for them to finish, its a bad use of threads in the first place
cheers

Why does MSDN sample from Threading Tutorial crash?

From sample example 4 of MSDN "Threading Tutorial"
Following code errors out at the line commented with "---errors is here---".
What is wrong?
using System;
using System.Threading;
public class MutexSample
{
static Mutex gM1;
static Mutex gM2;
const int ITERS = 100;
static AutoResetEvent Event1 = new AutoResetEvent(false);
static AutoResetEvent Event2 = new AutoResetEvent(false);
static AutoResetEvent Event3 = new AutoResetEvent(false);
static AutoResetEvent Event4 = new AutoResetEvent(false);
public static void Main(String[] args)
{
Console.WriteLine("Mutex Sample ...");
// Create Mutex initialOwned, with name of "MyMutex".
gM1 = new Mutex(true, "MyMutex");
// Create Mutex initialOwned, with no name.
gM2 = new Mutex(true);
Console.WriteLine(" - Main Owns gM1 and gM2");
AutoResetEvent[] evs = new AutoResetEvent[4];
evs[0] = Event1; // Event for t1
evs[1] = Event2; // Event for t2
evs[2] = Event3; // Event for t3
evs[3] = Event4; // Event for t4
MutexSample tm = new MutexSample();
Thread thread1 = new Thread(new ThreadStart(tm.t1Start));
Thread thread2 = new Thread(new ThreadStart(tm.t2Start));
Thread thread3 = new Thread(new ThreadStart(tm.t3Start));
Thread thread4 = new Thread(new ThreadStart(tm.t4Start));
thread1.Start(); // Does Mutex.WaitAll(Mutex[] of gM1 and gM2)
thread2.Start(); // Does Mutex.WaitOne(Mutex gM1)
thread3.Start(); // Does Mutex.WaitAny(Mutex[] of gM1 and gM2)
thread4.Start(); // Does Mutex.WaitOne(Mutex gM2)
Thread.Sleep(2000);
Console.WriteLine(" - Main releases gM1");
gM1.ReleaseMutex(); // t2 and t3 will end and signal
Thread.Sleep(1000);
Console.WriteLine(" - Main releases gM2");
gM2.ReleaseMutex(); // t1 and t4 will end and signal
// Waiting until all four threads signal that they are done.
WaitHandle.WaitAll(evs);
Console.WriteLine("... Mutex Sample");
}
public void t1Start()
{
Console.WriteLine("t1Start started, Mutex.WaitAll(Mutex[])");
Mutex[] gMs = new Mutex[2];
gMs[0] = gM1; // Create and load an array of Mutex for WaitAll call
gMs[1] = gM2;
Mutex.WaitAll(gMs); // Waits until both gM1 and gM2 are released
Thread.Sleep(2000);
Console.WriteLine("t1Start finished, Mutex.WaitAll(Mutex[]) satisfied");
Event1.Set(); // AutoResetEvent.Set() flagging method is done
}
public void t2Start()
{
Console.WriteLine("t2Start started, gM1.WaitOne( )");
gM1.WaitOne(); // Waits until Mutex gM1 is released ---errors is here---
Console.WriteLine("t2Start finished, gM1.WaitOne( ) satisfied");
Event2.Set(); // AutoResetEvent.Set() flagging method is done
}
public void t3Start()
{
Console.WriteLine("t3Start started, Mutex.WaitAny(Mutex[])");
Mutex[] gMs = new Mutex[2];
gMs[0] = gM1; // Create and load an array of Mutex for WaitAny call
gMs[1] = gM2;
Mutex.WaitAny(gMs); // Waits until either Mutex is released
Console.WriteLine("t3Start finished, Mutex.WaitAny(Mutex[])");
Event3.Set(); // AutoResetEvent.Set() flagging method is done
}
public void t4Start()
{
Console.WriteLine("t4Start started, gM2.WaitOne( )");
gM2.WaitOne(); // Waits until Mutex gM2 is released
Console.WriteLine("t4Start finished, gM2.WaitOne( )");
Event4.Set(); // AutoResetEvent.Set() flagging method is done
}
}
After waiting on a Mutex you have to release it, using
Mutex.ReleaseMutex()
before the threads exits.
fixed t1start - t4start
public void t1Start()
{
Console.WriteLine("t1Start started, Mutex.WaitAll(Mutex[])");
Mutex[] gMs = new Mutex[2];
gMs[0] = gM1; // Create and load an array of Mutex for WaitAll call
gMs[1] = gM2;
Mutex.WaitAll(gMs); // Waits until both gM1 and gM2 are released
Thread.Sleep(2000);
Console.WriteLine("t1Start finished, Mutex.WaitAll(Mutex[]) satisfied");
Event1.Set(); // AutoResetEvent.Set() flagging method is done
gM1.ReleaseMutex();
gM2.ReleaseMutex();
}
public void t2Start()
{
Console.WriteLine("t2Start started, gM1.WaitOne( )");
gM1.WaitOne(); // Waits until Mutex gM1 is released ---errors is here---
Console.WriteLine("t2Start finished, gM1.WaitOne( ) satisfied");
gM1.ReleaseMutex();
Event2.Set(); // AutoResetEvent.Set() flagging method is done
}
public void t3Start()
{
Console.WriteLine("t3Start started, Mutex.WaitAny(Mutex[])");
Mutex[] gMs = new Mutex[2];
gMs[0] = gM1; // Create and load an array of Mutex for WaitAny call
gMs[1] = gM2;
int result = Mutex.WaitAny(gMs); // Waits until either Mutex is released
gMs[result].ReleaseMutex();
Console.WriteLine("t3Start finished, Mutex.WaitAny(Mutex[])"); Event3.Set(); // AutoResetEvent.Set() flagging method is done
}
public void t4Start()
{
Console.WriteLine("t4Start started, gM2.WaitOne( )");
gM2.WaitOne(); // Waits until Mutex gM2 is released
Console.WriteLine("t4Start finished, gM2.WaitOne( )");
Event4.Set(); // AutoResetEvent.Set() flagging method is done
gM2.ReleaseMutex();
}

Categories

Resources