I have a method:
public void Run()
{
instalProgressPageViewModel.ExecuteButton_Click();
//waiting here
Environment.Exit(0);
}
Method Execute_Click() calls a installers of msi packages. Those installers run in separate threads:
this.uiDispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
new InstallationCompleted(this.completeInstallDelegate),
installationState);
where:
this.completeInstallDelegate // method which should be called after the thread is done.
Waiting for function CompleteInstall is crucial as its finalize installation and begins installation next msi package in a list of packages.
In the sample code of method Run app is closed before anything can happen.
I tried putting:
while(true){}
In a place of // waiting here and put breakpoint in CompleteInstall method to check if it will be called but it wasn't hit. App is stucked in infite loop inside while.
What can I do to force my main thread to wait for threads and jump into completeinstall method when its called by delegate?
#Update:
With your suggestions my code looks like this:
there is
public static ManualResetEvent mre // global object initialized in main
and other class is:
public void Run()
{
instalProgressPageViewModel.ExecuteButton_Click();
mre.WaitOne();
Environment.Exit(0);
}
ExecuteButton_Click call this function:
public void StartProcessing()
{
var processor = new Action(this.DoProcessing);
processor.BeginInvoke(null, null);
}
now DoProcessing:
private void DoProcessing()
{
var installationState = this.Execute();
// Schedule the update function in the UI thread.
this.uiDispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
new InstallationCompleted(this.completeInstallDelegate),
installationState);
}
and finally completeInstallDelegate
private void CompleteInstall(InstallationState installationState)
{
App.mre.Set();
/*
Some code
*/
this.PostInstallAndNext();
}
If I put break Point at the line App.mre.Set() it is never hit.
and for unknow reason for me the DoProcessing is called after mre.WaitOne(). Does Action and BeginInvoke work out of sync too?
Thanks for updating the question.
It looks like you are never creating an actual new Thread, i.e. you are suspending the main thread and effectively deadlocking your application.
You could create an new Thread here:
public void StartProcessing()
{
var thread = new Thread(() => this.DoProcessing);
thread.Start();
}
You could use the ManualResetEvent class.
Create a ManualResetEvet
ManualResetEvent mre = new ManualResetEvent(false);
In the Main method wait for this event to get signalled.
mre.WaitOne();
In your delegate (when the work is finished), signal the event.
mre.Set();
A simple solution would be to use ManualResetEvent.
You would then have a blocking call to WaitOne, until you call Set from the other thread.
Related
I try to log text messages from a Task or Thread to a textbox on my form. For that i use Invoke and InvokeRequired methods to syncronize with the main thread, as i can be found in many examples on the internet. See LogMessage_Delegate and LogMessage_Threadsafe below. When i close the app, a boolean flag finished is set to true and the task/thread should stop the work.
This all works fine until i set a breakpoint on the first line of the Form1_FormClosing event handler (finished = true;). Then i see only the console message "LogMessage InvokeRequired", but no corresponding "LogMessage" and the app is hanging.
If i comment out the LogMessage_Threadsafe call in Work (only console messages), then it works again. The app is closing, as expected.
So, can anybody explain this behavior to me? I can find no reason for it.
Please note, i do the flagging in the Form1_FormClosing event handler, so the form is still alive and working.
namespace MultiThreadedTest
{
public partial class Form1 : Form
{
//************************************************************
// Fields
Thread worker = null;
Task task = null;
bool finished = false;
//************************************************************
// Constructor
public Form1()
{
InitializeComponent();
worker = new Thread(Work);
worker.Start();
//task = Task.Factory.StartNew(Work);
}
//************************************************************
// Helper methods
public void LogMessage(string sMessage)
{
LogTextBox.Text += sMessage + Environment.NewLine;
}
/// <summary>
/// Threadsafe wrapper for LogMessage
/// </summary>
delegate void LogMessage_Delegate(string sMessage);
public void LogMessage_Threadsafe(string sMessage)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.InvokeRequired)
{
Console.WriteLine("LogMessage InvokeRequired");
LogMessage_Delegate callback = new LogMessage_Delegate(LogMessage_Threadsafe);
this.Invoke(callback, new object[] { sMessage });
}
else
{
Console.WriteLine("LogMessage");
LogMessage(sMessage);
}
}
//************************************************************
// Commands
void Work()
{
while (!finished)
{
Console.WriteLine("Tread/Task Waiting...");
LogMessage_Threadsafe("Tread/Task Waiting...");
Thread.Sleep(1000); // Wait a little...
}
Console.WriteLine("Thread/Task Done");
}
//************************************************************
// Events
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
finished = true;
if (worker != null) worker.Join();
if (task != null) Task.WaitAll(task);
Console.WriteLine("App Done");
}
}
}
You don't need to use raw threads since .NET 4 with the introduction of Tasks. Invoke wasn't needed either but became obsolete since .NET 4.5 with the introduction of async/await. 4.5 also introduced thread-safe progress reporting and cancellation with the IProgress< T> inteface and Progress< T> implementation, as explained in Async in 4.5: Enabling Progress and Cancellation in Async APIs.
Progress<T> calls its delegate on the thread it was created on, in this case the UI thread. You can pass the interface to any background method (task, thread method etc) and use it to report progress.
Given that the earliest supported .NET version is 4.5.2, you can assume these classes will always be available. BTW, TLS 1.2 support was added in 4.5.2 so any holdouts are forced to upgrade already, as they find they can't connect to GMail or other services that demand TLS 1.2.
Your code can be simplified a lot by using these classes. A quick&dirty form with a background timer and thread-safe reporting is the following:
public partial class Form1 : Form
{
System.Threading.Timer _timer;
IProgress<string> _progress;
public Form1()
{
InitializeComponent();
_progress = new Progress<string>(msg => textBox1.Text += msg + "\r\n");
_timer = new System.Threading.Timer(theCallback);
}
private async void theCallback(object state)
{
for (int i = 0; i < 5; i++)
{
await Task.Delay(100);
_progress.Report($"Boo {i}");
}
}
private void Form1_Load(object sender, EventArgs e)
{
_timer.Change(0, 10000);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
_timer.Dispose();
_timer = null;
_progress = null;
}
}
UPDATE
As for why the original code blocks, it's because Thread.Join() is called from the UI thread in Form.Closing. If the background thread tries to call Invoke to marshal a call to the UI thread, it will get blocked itself precisely because the UI thread is blocked.
This can be avoided by calling BeginInvoke instead of Invoke(). This was the typical way to handle callbacks into the UI thread before .NET 4.
The blocking behaviour can be seen in the Parallel Stacks debugger window (Debug / Windows / Parallel Stacks). When the form deadlocks, two stacks appear, one in the Form.Closing method and one in the LogMessage_Threadsafe method
If you're paused at a breakpoint in the UI thread, calls marshaled to the UI thread via Invoke won't execute, because they run on the UI thread, which is paused.
But judging from your comment, that doesn't seem to be the issue. So I would guess the problem is that, by pausing at that breakpoint, you've allowed the background thread to get into a state where it's blocking on Invoke(), and then you're trying to join that background thread, which will block until the Invoke completes, which will never happen.
As a separate issue, if you're accessing finished from multiple threads, you need to surround the reads and writes with lock blocks to ensure thread safety.
I am working on a legacy application that is built on top of NET 3.5. This is a constraint that I can't change.
I need to execute a second thread to run a long running task without locking the UI. When the thread is complete, somehow I need to execute a Callback.
Right now I tried this pseudo-code:
Thread _thread = new Thread(myLongRunningTask) { IsBackground = True };
_tread.Start();
// wait until it's done
_thread.Join();
// execute finalizer
The second option, which does not lock the UI, is the following:
Thread _thread = new Thread(myLongRunningTask) { IsBackground = True };
_tread.Start();
// wait until it's done
while(_thread.IsAlive)
{
Application.DoEvents();
Thread.Sleep(100);
}
// execute finalizer
Of course the second solution is not good cause it overcharge the UI.
What is the correct way to execute a callback when a _thread is complete? Also, how do I know if the thread was cancelled or aborted?
*Note: * I can't use the BackgroundWorker and I can't use the Async library, I need to work with the native thread class.
There are two slightly different kinds of requirement here:
Execute a callback once the long-running task has completed
Execute a callback once the thread in which the long-running task was running has completed.
If you're happy with the first of these, the simplest approach is to create a compound task of "the original long-running task, and the callback", basically. You can even do this just using the way that multicast delegates work:
ThreadStart starter = myLongRunningTask;
starter += () => {
// Do what you want in the callback
};
Thread thread = new Thread(starter) { IsBackground = true };
thread.Start();
That's very vanilla, and the callback won't be fired if the thread is aborted or throws an exception. You could wrap it up in a class with either multiple callbacks, or a callback which specifies the status (aborted, threw an exception etc) and handles that by wrapping the original delegate, calling it in a method with a try/catch block and executing the callback appropriately.
Unless you take any special action, the callback will be executed in the background thread, so you'll need to use Control.BeginInvoke (or whatever) to marshal back to the UI thread.
I absolutely understand your requirements, but you've missed one crucial thing: do you really need to wait for the end of that thread synchronously? Or maybe you just need to execute the "finalizer" after thread's end is detected?
In the latter case, simply wrap the call to myLongRunningTask into another method:
void surrogateThreadRoutine() {
// try{ ..
mytask();
// finally { ..
..all 'finalization'.. or i.e. raising some Event that you'll handle elsewhere
}
and use it as the thread's routine. That way, you'll know that the finalization will occur at the thread's and, just after the end of the actual job.
However, of course, if you're with some UI or other schedulers, the "finalization" will now run on yours thread, not on the "normal threads" of your UI or comms framework. You will need to ensure that all resources are external to your thread-task are properly guarded or synchronized, or else you'll probably clash with other application threads.
For instance, in WinForms, before you touch any UI things from the finalizer, you will need the Control.InvokeRequired (surely=true) and Control.BeginInvoke/Invoke to bounce the context back to the UI thread.
For instance, in WPF, before you touch any UI things from the finalizer, you will need the Dispatcher.BeginInvoke..
Or, if the clash could occur with any threads you control, simple proper lock() could be enough. etc.
You can use a combination of custom event and the use of BeginInvoke:
public event EventHandler MyLongRunningTaskEvent;
private void StartMyLongRunningTask() {
MyLongRunningTaskEvent += myLongRunningTaskIsDone;
Thread _thread = new Thread(myLongRunningTask) { IsBackground = true };
_thread.Start();
label.Text = "Running...";
}
private void myLongRunningTaskIsDone(object sender, EventArgs arg)
{
label.Text = "Done!";
}
private void myLongRunningTask()
{
try
{
// Do my long task...
}
finally
{
this.BeginInvoke(Foo, this, EventArgs.Empty);
}
}
I checked, it's work under .NET 3.5
You could use the Observer Pattern, take a look here:
http://www.dofactory.com/Patterns/PatternObserver.aspx
The observer pattern will allow you, to notify other objects which were previously defined as observer.
A very simple thread of execution with completion callback
This does not need to run in a mono behavior and is simply used for convenience
using System;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
public class ThreadTest : MonoBehaviour
{
private List<int> numbers = null;
private void Start()
{
Debug.Log("1. Call thread task");
StartMyLongRunningTask();
Debug.Log("2. Do something else");
}
private void StartMyLongRunningTask()
{
numbers = new List<int>();
ThreadStart starter = myLongRunningTask;
starter += () =>
{
myLongRunningTaskDone();
};
Thread _thread = new Thread(starter) { IsBackground = true };
_thread.Start();
}
private void myLongRunningTaskDone()
{
Debug.Log("3. Task callback result");
foreach (int num in numbers)
Debug.Log(num);
}
private void myLongRunningTask()
{
for (int i = 0; i < 10; i++)
{
numbers.Add(i);
Thread.Sleep(1000);
}
}
}
Try to use ManualRestEvent to signal of thread complete.
Maybe using conditional variables and mutex, or some functions like wait(), signal(), maybe timed wait() to not block main thread infinitely.
In C# this will be:
void Notify()
{
lock (syncPrimitive)
{
Monitor.Pulse(syncPrimitive);
}
}
void RunLoop()
{
for (;;)
{
// do work here...
lock (syncPrimitive)
{
Monitor.Wait(syncPrimitive);
}
}
}
more on that here:
Condition Variables C#/.NET
It is the concept of Monitor object in C#, you also have version that enables to set timeout
public static bool Wait(
object obj,
TimeSpan timeout
)
more on that here:
https://msdn.microsoft.com/en-us/library/system.threading.monitor_methods(v=vs.110).aspx
Can anyone give me a headstart on the topic of threading? I think I know how to do a few things but I need to know how to do the following:
Setup a main thread that will stay active until I signal it to stop(in case you wonder, it will terminate when data is received). Then i want a second thread to start which will capture data from a textbox and should quit when I signal it to that of which occurs when the user presses the enter key.
Cheers!
This is how I do it...
public class ThreadA {
public ThreadA(object[] args) {
...
}
public void Run() {
while (true) {
Thread.sleep(1000); // wait 1 second for something to happen.
doStuff();
if(conditionToExitReceived) // what im waiting for...
break;
}
//perform cleanup if there is any...
}
}
Then to run this in its own thread... ( I do it this way because I also want to send args to the thread)
private void FireThread(){
Thread thread = new Thread(new ThreadStart(this.startThread));
thread.start();
}
private void (startThread){
new ThreadA(args).Run();
}
The thread is created by calling "FireThread()"
The newly created thread will run until its condition to stop is met, then it dies...
You can signal the "main" with delegates, to tell it when the thread has died.. so you can then start the second one...
Best to read through : This MSDN Article
Thread th = new Thread(function1);
th.Start();
th.Abort();
void function1(){
//code here
}
Use a static AutoResetEvent in your spawned threads to call back to the main thread using the Set() method. This guy has a fairly good demo in SO on how to use it.
AutoResetEvent clarification
I tried the following (pseudocode) but I always get a deadlock when Iam trying to stop my thread.
The problem is that Join() waits for the thread to complete and a pending Invoke() operation is also waiting to complete. How can I solve this?
Thread workerThread = new Thread(BackupThreadRunner);
volatile bool cancel;
// this is the thread worker routine
void BackupThreadRunner()
{
while (!cancel)
{
DoStuff();
ReportProgress();
}
}
// main thread
void ReportProgress()
{
if (InvokeRequired)
{
Invoke(ReportProgress);
}
UpdateStatusBarAndStuff();
}
// main thread
void DoCancel()
{
cancel=true;
workerThread.Join();
}
You could use BeginInvoke(ReportProgress) - that way your worker thread doesn't have to wait for the UpdateStatusBarAndStuff method to finish.
use `BeginInvoke' instead
I would do it a slightly different way:
private Thread workerThread;
void StartButtonClick()
{
workerThread = new Thread(ReportProgress);
thread.Start();
}
void CancelButtonClick()
{
// If you use a while(bool), it will repeat the task forever
// or with no while and just a bool, you'll have to check the value of the bool in each line
// so simply aborting it (providing you clean up) is accceptable.
workerThread.Abort();
// If you don't mind your user waiting:
// workerThread.Join(1000);
}
void ReportProgress()
{
if (InvokeRequired)
{
Invoke(ReportProgress);
return;
}
UpdateStatusBarAndStuff();
}
The best practice advice is "don't abort". This is based on the fact you don't know at what point the abort call will exit your code - it could be half way through creating a Stream. So you end up with a choice: can you guarantee that at whatever line the code exits, it will be in a reasonable state to do so?
If you can't then you will need to use a Thread.Join().
Even with a Thread.Join, the user may get bored and quit (ALT+F4) the app, and you have exactly the same situation as you had with the Thread.Abort() call.
I am having a function where I have used a thread in c#.net.
I am having a another function on the next line of that thread. But this function has to be called only after the thread gets executed.
How can i do it ?
Example..
Somefunction()
{
// thread //(thread started)
add() (another function but need to be executed only tha above thread gets over)
}
Use a BackgroundWorker and include the function call in the worker completeted event handler.
var worker = new BackgroundWorker();
_worker.DoWork += delegate { DoStuff(); };
_worker.RunWorkerCompleted += worker_RunWorkerCompleted;
_worker.RunWorkerAsync();
[...]
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
/// Do post-thread stuff
}
Use Thread.Join to block the current thread until the specified thread has finished execution.
Why start a separate thread if you want execution to be single threaded?
by "after the thread gets executed", do you mean it must have started? or it must have finished?
If you mean finished, then you would typically Join() the thread - but there is no point Join()ing a thread you have stared in the line before (just execute the code directly). The other approach is to use a "callback" at the end of the threaded method.
If you mean started, then you can do things like:
object lockObj = new object();
lock(lockObj) {
ThreadPool.QueueUserWorkItem(delegate {
lock(lockObj) {
Monitor.Pulse(lockObj);
}
// do things (we're on the second thread...)
});
Monitor.Wait(lockObj);
}
// thread has definitely started here
You can use , for instance, a ManualResetEvent.
When you start the processing on the other thread, you call the reset method.
When processing on the other thread has finished, you call set.
Then, the method that must be executed on the 'main thread', needs to wait until the ManualResetEvent has been set before it can execute.
For more info, you can have a look at the ManualResetEvent at MSDN.
If add() is thread safe, just call it at the end of the function you pass to create thread.
You could try the following, it may not work for your scenario: I can't tell given the amount of detail you provided:
First create a delegate:
public delegate int MyThreadSignature(Something arg);
Then use the Begin/End Invoke pattern:
var thread = new MyThreadSignature(WorkerMethod);
thread.BeginInvoke(theArg,
MyThreadEnded, /*Method to call when done*/,
thread /*AsyncState*/);
Create the MyThreadEnded method:
void MyThreadEnded(IAsyncResult result)
{
var thread = (MyThreadSignature)result.AsyncState;
var result = thread.EndInvoke(result);
// Call your next worker here.
}
The method to call MUST have the signature in the example: Name(IAsyncResult result).