How to wait for a thread to finish execution in C#? - c#

I have a function that is called in rapid succession that has a open database connection.
my issue is that before one database connection is closed, another instance of the function is called and i could possibly receive a deadlock in the database.
I have tried:
private static WaitHandle[] waitHandles = new WaitHandle[]
{
new AutoResetEvent(false)
};
protected override void Broadcast(Data data, string updatedBy)
{
Action newAction = new Action(() =>
{
DataManagerFactory.PerformWithDataManager(
dataManager =>
{
// Update status and broadcast the changes
data.UpdateModifiedColumns(dataManager, updatedBy);
BroadcastManager.Instance().PerformBroadcast(
data,
BroadcastAction.Update,
Feature.None);
},
e => m_log.Error(ServerLog.ConfigIdlingRequestHandler_UpdateFailed() + e.Message));
}
);
Thread workerThread = new Thread(new ThreadStart(newAction));
ThreadPool.QueueUserWorkItem(workerThread.Start, waitHandles[0]);
WaitHandle.WaitAll(waitHandles);
}
but i recieve a thread error and the program freezes. It has something to do with the thread start function having no parameters i believe.
Thanks for any help

This is how it's done. Create class that does the job:
public class MyAsyncClass
{
public delegate void NotifyComplete(string message);
public event NotifyComplete NotifyCompleteEvent;
//Starts async thread...
public void Start()
{
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(DoSomeJob));
t.Start();
}
void DoSomeJob()
{
//just wait 5 sec for nothing special...
System.Threading.Thread.Sleep(5000);
if (NotifyCompleteEvent != null)
{
NotifyCompleteEvent("My job is completed!");
}
}
}
Now this is code from another class, that calls first one:
MyAsyncClass myClass = null;
private void button2_Click(object sender, EventArgs e)
{
myClass = new MyAsyncClass();
myClass.NotifyCompleteEvent += new MyAsyncClass.NotifyComplete(myClass_NotifyCompleteEvent);
//here I start the job inside working class...
myClass.Start();
}
//here my class is notified from working class when job is completed...
delegate void myClassDelegate(string message);
void myClass_NotifyCompleteEvent(string message)
{
if (this.InvokeRequired)
{
Delegate d = new myClassDelegate(myClass_NotifyCompleteEvent);
this.Invoke(d, new object[] { message });
}
else
{
MessageBox.Show(message);
}
}
Let me know if I need to explain some details.
Alternative to this is BackgroudWorker:

Related

WCF callback not working as expected

I made a WCF service which makes a callback to a WPF client. I just show the progress in a textbox in the WPF client. What I got first is cross thread operation not valid. Then I modified the client side code and implemented using methods such as Invoke() and BeginInvoke(). Now the client side code shows only the value 100%. Actually it should display the values from 0-100%. Any solutions?
The code at wcf service:
namespace ReportService
{
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant,InstanceContextMode=InstanceContextMode.Single)]
public class Report : IReportService
{
public void ProcessReport()
{
for (int i = 1; i <= 100; i++)
{
Thread.Sleep(1000);
OperationContext.Current.GetCallbackChannel<IReportCallback>().ReportProgress(i);
}
}
}
}
Code at client:
namespace Report
{
[CallbackBehavior(UseSynchronizationContext=false)]
public partial class Form1 : Form,ReportService.IReportServiceCallback
{
delegate void delSetTxt(int percentCompleted);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
InstanceContext ic= new InstanceContext(this);
ReportService.ReportServiceClient client = new ReportService.ReportServiceClient(ic);
client.ProcessReport();
}
public void ReportProgress(int percentCompleted)
{
// this.Invoke(new Action(() => { this.textBox1.Text = percentCompleted.ToString(); }));
Thread t = new Thread(() => setTxt(percentCompleted));
t.Start();
}
public void setTxt(int percentCompleted)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new delSetTxt(setTxt), new object[] { percentCompleted });
return;
}
this.textBox1.Text = percentCompleted.ToString() + " % complete";
}
}
}
When the call is made to the service, the GUI thread is stuck in the button_click method.
So the GUI thread must not be frozen.
There are (at least) two solutions that work, I tested them :
Put [OperationContract(IsOneWay = true)] both on the server and the callback operation
Put [OperationContract(IsOneWay = true)] on the callback operation and don't lock GUI thread with await/async:
private async void button1_Click(object sender, EventArgs e)
{
InstanceContext ic = new InstanceContext(this);
ReportServiceClient client = new ReportServiceClient(ic);
await client.ProcessReportAsync();
//client.ProcessReport();
}
Good luck

how to notify method that something is done

My constructor besides other things call another method DoWork
public MyTask(TaskAction action)
{
DoWork(action);
}
DoWork method goes to another method Calc(2)
private void Calc (int 2){
... calc and save result into file
}
How can I alert MyTask that Calc is done and let MyTask to continue further.
P.S. I could read hdd every few secs in order to see whether file with result is save and based on that continue further, but I assume that there is better way.
BackgroundWorker class allows you to easily manage your async work.
BackgroundWorker _worker = new BackgroundWorker();
public Cnt()
{
InitializeComponent();
_worker.DoWork += WorkerOnDoWork;
_worker.RunWorkerCompleted += WorkerOnRunWorkerCompleted;
//start your work
_worker.RunWorkerAsync();
}
private void WorkerOnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//Worker completed event
}
private void WorkerOnDoWork(object sender, DoWorkEventArgs e)
{
//Do
}
There are many ways to do this.The latest recommended is using tasks
Task taskA = new Task(() => { Console.WriteLine("Task A started"); });
taskA.ContinueWith((ss) => { Console.WriteLine("Task A finished"); });
taskA.Start();
http://msdn.microsoft.com/en-us/library/ee372288(v=vs.110).aspx
This way you can block the current thread if you want.
Another way is the BackGroundWorker Class
Also, you can use a custom callback like this
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
DoWorkA(DoWorkFinished);
Console.Read();
}
private static void DoWorkA(Action whatToDoWhenFinished)
{
Console.WriteLine("Doing something");
whatToDoWhenFinished();
}
private static void DoWorkFinished()
{
Console.WriteLine("Doing something Else");
}
}
}

How to Wake up a sleeping thread?

I made a thread at load event like below:
Thread checkAlert = null;
bool isStop = false;
private void frmMain_Load(object sender, EventArgs e)
{
checkAlert = new Thread(CheckAlert);
checkAlert.Start();
}
void CheckAlert()
{
while (!isStop)
{
Thread.Sleep(60000);
//do work here
}
}
Is there any way to resume the checkAlert thread during it's sleep period?( Thread.Sleep(60000);)
I tried using Thread.Interrupt() but it flows a ThreadInterruptedException, how should I handle this exception? or is there any way to resume the thread?
Edited:
I need to wake up the thread before the "sleep" end because when the user wants to quit the program, the program will have to wait for some time before it really quits ( checkAlert is still running) Is there any way to improve this case?
Based on your comments what it looks like is you need to re-design how CheckAlert works so it does not use Sleep's at all. What you should be doing is using a Timer instead.
System.Timers.Timer timer = null;
public FrmMain()
{
InitializeComponent();
timer = new System.Timers.Timer(60000);
timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
//If you want OnTimedEvent to happen on the UI thread instead of a ThreadPool thread, uncomment the following line.
//timer.SynchronizingObject = this;
if(this.components == null)
this.components = new System.ComponentModel.Container();
//This makes it so when the form is disposed the timer will be disposed with it.
this.componets.Add(timer);
}
private void frmMain_Load(object sender, EventArgs e)
{
timer.Start();
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
//It is good practice not to do complicated logic in a event handler
// if we move the logic to its own method it is much easier to test (you are writing unit tests, right? ;) )
CheckAlert();
}
void CheckAlert()
{
//do work here
}
private void frmMain_Close(object sender, EventArgs e)
{
timer.Stop();
}
If you want the thread to exit automatically when your program quits, simply make it a background thread.
checkAlert = new Thread(CheckAlert);
checkAlert.IsBackground = true;
checkAlert.Start();
It looks to me like you're trying to create a thread which handles two types of events: do something and stop running.
Rather than using a shared variable (isStop) and some other technique to interrupt the thread in order to do work, you might want to use threading events (not to be confused high-level UI Event objects) to control your thread.
AutoResetEvent stop = new AutoResetEvent(false);
AutoResetEvent check = new AutoResetEvent(false);
private void CheckAlert() {
WaitHandle[] handles = new WaitHandle[] { stop, check };
for (;;) {
switch (AutoResetEvent.WaitAny(handles)) {
case 0:
return;
case 1:
// do work
break;
}
}
}
Calling check.Set() in your code will trigger the "do work" branch in the thread and stop.Set() will cause the thread to terminate gracefully.
Once your code has called stop.Set() to terminate the thread, it can call the thread's Join() method to wait until the thread terminates.
EDIT
I misunderstood the question. I will leave the code above in case anyone finds it useful.
If all you want to do is have a thread that performs a task once a minute and stop on demand, you can use the following code:
AutoResetEvent stop = new AutoResetEvent(false);
void CheckAlert() {
var time = new TimeSpan(0, 1, 0); // one minute
while (!stop.WaitOne(time)) {
// do work
}
}
private Thread checkThread;
private void frmMain_Load(object sender, EventArgs e) {
checkThread = new Thread(CheckAlert);
checkThread.Start();
}
private void frmMain_Close(object sender, EventArgs e) {
stop.Set(); // signal thread to stop
checkThread.Join(); // wait for thread to terminate
}
You can see an explanation on how to wake a sleeping thread here:
https://msdn.microsoft.com/en-us/library/tttdef8x%28v=vs.100%29.aspx
and this is a complete example (as you can see, Thread.Interrupt is the good choise... however you have to catch it to continue normal thread execution):
public class HVCSensor : HVCDevice, IDisposable
{
private Thread myThread;
private const int execute_timeout = ((10 + 10 + 6 + 3 + 15 + 15 + 1 + 1 + 15 + 10) * 1000);
private bool disposed = false;
private bool paused = false;
public delegate void HVCResultsHandler(HVC_RESULT res);
public event HVCResultsHandler HVCResultsArrived;
private void OnHVCResultsArrived(HVC_RESULT res)
{
if (HVCResultsArrived != null) {
HVCResultsArrived(res);
}
}
public HVCSensor() {
myThread = new Thread(new ThreadStart(this.execute));
}
private void execute(){
while (!disposed) {
if (!paused && this.IsConnected)
{
HVC_RESULT outRes;
byte status;
try
{
this.ExecuteEx(execute_timeout, activeDetections, imageAcquire, out outRes, out status);
OnHVCResultsArrived(outRes);
}
catch (Exception ex) {
}
}
else {
try
{
Thread.Sleep(1000);
}
catch (ThreadInterruptedException e)
{
}
}
}
}
public HVC_EXECUTION_IMAGE imageAcquire
{
get;
set;
}
public HVC_EXECUTION_FLAG activeDetections
{
get;
set;
}
public void startDetection() {
if(myThread.ThreadState==ThreadState.Unstarted)
myThread.Start();
}
public void pauseDetection() {
paused = true;
}
public void resumeDetection() {
paused = false;
if (myThread.ThreadState == ThreadState.WaitSleepJoin)
myThread.Interrupt();
}
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
disposed = true;
myThread.Interrupt();
}
}

Joining a thread started with StartNew()

When using the StartNew() method to kick off a process on a new thread, I need to figure out how to make another call into this object in that same thread (I assume this would be some sort of Join operation?).
The following example is dumbed down to illustrate the meat of what I am trying to do. I am well aware it is severely lacking in basic concurrency considerations. But I didn't want to cloud the code with all of that logic, so please forgive me on that.
The following console app shows what I am trying to accomplish. Assume on the StartNew() call a new thread with ID 9976 is created and the method invoked there. I would like the subsequent call to ProcessImmediate() in the file system watcher change event handler to be made on thread 9976 as well. As it stands, the call would share the same thread that is used for the file system watcher change event.
Can this be done, and if so, how?
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var runner = new Runner();
runner.Run();
Console.ReadKey();
}
}
public class Runner
{
private Activity _activity = null;
private FileSystemWatcher _fileSystemWatcher;
public void Run()
{
_activity = new Activity();
// start activity on a new thread
Task.Factory.StartNew(() => _activity.Go());
_fileSystemWatcher = new FileSystemWatcher();
_fileSystemWatcher.Filter = "*.watcher";
_fileSystemWatcher.Path = "c:\temp";
_fileSystemWatcher.Changed += FileSystemWatcher_Changed;
_fileSystemWatcher.EnableRaisingEvents = true;
}
private void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
{
// WANT TO CALL THIS FOR ACTIVITY RUNNING ON PREVIOUSLY CALLED THREAD
_activity.ProcessImmediate();
}
}
public class Activity
{
public void Go()
{
while (!Stop)
{
// for purposes of this example, magically assume that ProcessImmediate has not been called when this is called
DoSomethingInteresting();
System.Threading.Thread.Sleep(2000);
}
}
protected virtual void DoSomethingInteresting() { }
public void ProcessImmediate()
{
// for purposes of this example, assume that Go is magically in its sleep state when ProcessImmediate is called
DoSomethingInteresting();
}
public bool Stop { get; set; }
}
}
* UPDATE *
Thanks for the excellent responses. I took Mike's suggestion and implemented it for my console app. Below is the full working code which also includes the use of a cancellation token. I post this in case someone else might find it useful.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var runner = new Runner();
runner.Run();
Console.ReadKey();
runner.Stop();
Console.ReadKey();
}
}
public class Runner
{
private Activity _activity = null;
private FileSystemWatcher _fileSystemWatcher;
private CancellationTokenSource _cts = new CancellationTokenSource();
public void Stop() { _cts.Cancel(); }
public void Run()
{
_activity = new Activity();
// start activity on a new thread
var task = new Task(() => _activity.Go(_cts.Token), _cts.Token, TaskCreationOptions.LongRunning);
task.Start();
_fileSystemWatcher = new FileSystemWatcher();
_fileSystemWatcher.Filter = "*.watcher";
_fileSystemWatcher.Path = "C:\\Temp\\FileSystemWatcherPath";
_fileSystemWatcher.Changed += FileSystemWatcher_Changed;
_fileSystemWatcher.EnableRaisingEvents = true;
}
private void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
{
// WANT TO CALL THIS FOR ACTIVITY RUNNING ON PREVIOUSLY CALLED THREAD
_activity.ProcessImmediate();
}
}
public class Activity : IDisposable
{
private AutoResetEvent _processing = new AutoResetEvent(false);
public void Go(CancellationToken ct)
{
Thread.CurrentThread.Name = "Go";
while (!ct.IsCancellationRequested)
{
// for purposes of this example, magically assume that ProcessImmediate has not been called when this is called
DoSomethingInteresting();
_processing.WaitOne(5000);
}
Console.WriteLine("Exiting");
}
protected virtual void DoSomethingInteresting()
{
Console.WriteLine(string.Format("Doing Something Interesting on thread {0}", Thread.CurrentThread.ManagedThreadId));
}
public void ProcessImmediate()
{
// for purposes of this example, assume that Go is magically in its sleep state when ProcessImmediate is called
_processing.Set();
}
public void Dispose()
{
if (_processing != null)
{
_processing.Dispose();
_processing = null;
}
}
}
}
First, you should use TaskCreationOptions.LongRunning if you are creating a task that will not complete quickly. Second, use an AutoResetEvent to signal the waiting thread to wake up. Note that below ProcessImmediate will return before DoSomethingInteresting has completed running on the other thread. Example:
using System.Threading;
public class Activity : IDisposable
{
private AutoResetEvent _processing = new AutoResetEvent(false);
public void Go()
{
while (!Stop)
{
// for purposes of this example, magically assume that ProcessImmediate has not been called when this is called
DoSomethingInteresting();
_processing.WaitOne(2000);
}
}
protected virtual void DoSomethingInteresting() { }
public void ProcessImmediate()
{
_processing.Set();
}
public bool Stop { get; set; }
public void Dispose()
{
if (_processing != null)
{
_processing.Dispose();
_processing = null;
}
}
}
User mike has given a better solution, which will be appropriate when you like to call the same method immediately. If you want to call a different methods immediately I'll expand mike's answer to achieve that.
using System.Threading;
public class Activity : IDisposable
{
private AutoResetEvent _processing = new AutoResetEvent(false);
private ConcurrentQueue<Action> actionsToProcess = new ConcurrentQueue<Action>();
public void Go()
{
while (!Stop)
{
// for purposes of this example, magically assume that ProcessImmediate has not been called when this is called
DoSomethingInteresting();
_processing.WaitOne(2000);
while(!actionsToProcess.IsEmpty)
{
Action action;
if(actionsToProcess.TryDeque(out action))
action();
}
}
}
protected virtual void DoSomethingInteresting() { }
public void ProcessImmediate(Action action)
{
actionsToProcess.Enqueue(action);
_processing.Set();
}
public bool Stop { get; set; }
public void Dispose()
{
if (_processing != null)
{
_processing.Dispose();
_processing = null;
}
}
}
To execute different methods on the same thread you can use a message loop that dispatches incoming requests. A simple option would be to use the event loop scheduler of the Reactive Extensions and to "recursively" schedule your Go() function - if in the mean time a different operation is scheduled it would be processed before the next Go() operation.
Here is a sample:
class Loop
: IDisposable
{
IScheduler scheduler = new EventLoopScheduler();
MultipleAssignmentDisposable stopper = new MultipleAssignmentDisposable();
public Loop()
{
Next();
}
void Next()
{
if (!stopper.IsDisposed)
stopper.Disposable = scheduler.Schedule(Handler);
}
void Handler()
{
Thread.Sleep(1000);
Console.WriteLine("Handler: {0}", Thread.CurrentThread.ManagedThreadId);
Next();
}
public void Notify()
{
scheduler.Schedule(() =>
{
Console.WriteLine("Notify: {0}", Thread.CurrentThread.ManagedThreadId);
});
}
public void Dispose()
{
stopper.Dispose();
}
}
static void Main(string[] args)
{
using (var l = new Loop())
{
Console.WriteLine("Press 'q' to quit.");
while (Console.ReadKey().Key != ConsoleKey.Q)
l.Notify();
}
}

How to call a completion method everytime ThreadPool.QueueUserWorkItem method is returned

I am using
System.Threading.ThreadPool.QueueUserWorkItem(x => MyMethod(param1, param2, param3, param4, param5));
I want to call the following method from the main thread every time the call to MyMethod is completed:
UpdateGui()
{
}
How do I do that?
Thanks!
Keep a global counter of work items queued and an object to protect it:
int runningTasks = 0;
object locker = new object();
Every time a task is added increment the counter:
lock(locker) runningTasks++;
System.Threading.ThreadPool.QueueUserWorkItem(x => MyMethod(param1, param2, param3, param4, param5));
At the end of MyMethod decrement the counter and signal the main thread:
lock(locker)
{
runningTasks--;
Monitor.Pulse(locker);
}
In the main thread (assuming this is not the GUI thread!):
lock(locker)
{
while(runningTasks > 0)
{
Monitor.Wait(locker);
UpdateGUI();
}
}
This way you also have a barrier to wait for all pending tasks to finish.
In case you don't want to wait, just skip the main thread completely and call UpdateGUI to forward updates to the GUI thread when MyMethod finishes.
Note that inside MyMethod you should have some form of Dispatcher.BeginInvoke (WPF) or Control.BeginInvoke (WinForms) otherwise you cannot update the GUI safely!
Post a call to the updategui method back to the sync context for the ui thread at the end of the threadpool method...
Example:
private SynchronizationContext _syncContext = null;
public Form1()
{
InitializeComponent();
//get hold of the sync context
_syncContext = SynchronizationContext.Current;
}
private void Form1_Load(object sender, EventArgs e)
{
//queue a call to MyMethod on a threadpool thread
ThreadPool.QueueUserWorkItem(x => MyMethod());
}
private void MyMethod()
{
//do work...
//before exiting, call UpdateGui on the gui thread
_syncContext.Post(
new SendOrPostCallback(
delegate(object state)
{
UpdateGui();
}), null);
}
private void UpdateGui()
{
MessageBox.Show("hello from the GUI thread");
}
Assuming that MyMethod is a synchronous method, invoked inside QueueUserWorkItem in order to make it execute asynchronously, the following approach may be used:
ThreadPool.QueueUserWorkItem(x =>
{
MyMethod(param1, param2, param3, param4, param5);
UpdateGui();
});
Note that you have to update GUI elements inside UpdateGui() by calling Invoke/BeginInvoke.
This may keep the client cleaner letting the class handle the cross threading switching mechanism. This way the GUI consumes your class in normal fashion.
public partial class Form1 : Form
{
private ExampleController.MyController controller;
public Form1()
{
InitializeComponent();
controller = new ExampleController.MyController((ISynchronizeInvoke) this);
controller.Finished += controller_Finished;
}
void controller_Finished(string returnValue)
{
label1.Text = returnValue;
}
private void button1_Click(object sender, EventArgs e)
{
controller.SubmitTask("Do It");
}
}
The GUI form subscribes to events of the class unaware they are mulch-threaded.
public class MyController
{
private ISynchronizeInvoke _syn;
public MyController(ISynchronizeInvoke syn) { _syn = syn; }
public event FinishedTasksHandler Finished;
public void SubmitTask(string someValue)
{
System.Threading.ThreadPool.QueueUserWorkItem(state => submitTask(someValue));
}
private void submitTask(string someValue)
{
someValue = someValue + " " + DateTime.Now.ToString();
System.Threading.Thread.Sleep(5000);
//Finished(someValue); This causes cross threading error if called like this.
if (Finished != null)
{
if (_syn.InvokeRequired)
{
_syn.Invoke(Finished, new object[] { someValue });
}
else
{
Finished(someValue);
}
}
}
}

Categories