update my label in different Thread and wait for the result - c#

In my application I am start process (Tshark) and start capturing, after I am finish to capturing I am checking the created file and parse from the process output the number of received packets in order to update my UI.
in this point if the created file is big all the UI stuck until the result on number of packets received so I want to do it in different Thread.
Capinfos capInfo = new Capinfos(); //my class who return the number of packets
ThreadStart tStarter = delegate {label.Text = capInfo._numberOfPackets.ToString("#,##0"); };
Thread thread = new Thread(tStarter);
thread.IsBackground = true;
thread.Start();
This code return a cross threading error.

You're doing it the wrong way round. You should be performing the packet capture in a different thread, only accessing the UI elements within the UI thread.
There are loads of different ways of doing this. The most common are probably:
You can use Control.Invoke and Control.BeginInvoke to marshal back to the UI thread when you need to
You can use BackgroundWorker which does some of this for you; you'd hook up the progress reporting event to update the UI from the right thread
If you're using C# 5 and .NET 4.5 you could use async/await to automatically get back to the UI thread within a single asynchronous method

It appears that you're trying to update the UI using a thread other than the UI thread (label.Text = ---). I think that is probably what the problem is. You could use Tasks to achieve asynchrony. You could use the Task's ContinueWith method to wait on the task to finish before updating your UI thread using BeginInvoke.
http://msdn.microsoft.com/en-us/library/dd235678.aspx

Related

C# worker thread with event driven work and no shut down

Here's what I woulld like to do:
Create a worker thread in my main thread (which controls the UI).
The worker thread keeps running until shut down by the main thread (which only happens when the entire application is shut down).
The main thread listens for keyup, but sends an event to the worker thread to process the keyup asynchronously (to avoid blocking the UI).
The worker thread updates the UI when the keyup has been handled.
So far I've just been creating a new thread every time there is a keyup, but it seems there is just too much overhead this way.
As far as I can tell, I should use the BackgroundWorker class, but the examples I've seen seems to start a background worker, continue with non-blocked UI in the main thread and update UI from the BackgroundWorker when it's finished - i.e. exactly the same as I'm already doing.
How to make it so the worker thread keeps running and sleep when there is no work to be done?
While Zaches answer is completely valid (and an approach I used for some time) I've stumbled upon what I think is a more elegant solution using Dispatcher:
Create the worker thread:
Dispatcher _workerDispatcher;
Thread _workerThread = new Thread(new ThreadStart(() =>
{
_workerDispatcher = Dispatcher.CurrentDispatcher; // Required to create the dispatcher
Dispatcher.Run(); // Keeps thread alive and creates a queue for work
});
_workerThread.Start();
Put work into the worker thread (from main thread or another thread):
// Synchronous work
_workerDispatcher.Invoke(() =>
{
// Do stuff
});
// Asynchronous work (makes most sense for background work)
_workerDispatcher.BeginInvoke(() =>
{
// Do stuff
});
Shut down the worker thread:
_workerDispatcher.InvokeShutdown();
_workerThread.Join(); // Wait for thread to shut down
I'm using new Thread() because I need to set apartment state, but you can also use tasks created using Task.Run() and Task.Factory.StartNew().
I'm not 100% certain that it's necessary to call thread.Join(), but I'd rather be certain that the thread has been shut down. If you're using a Task call task.Wait() instead.
Another way to get the Dispatcher is to call Dispatcher.FromThread(thread), but it's important to note that a Dispatcher is NOT created until CurrentDispatcher has been used (even if you don't use the reference later).
A downside of this approach is that it can't be used to have multiple threads pick items out of a queue and do work - for that you will have to use the producer/consumer approached described in Zaches answer. The dispatcher approach allows you to queue up work in a specific thead.
Why don't you just use the Task Parallel Library?
Create a new task whenever you detect the KeyUp event, and let TPL worry about creating new threads. Since it uses the thread pool, a new thread will not be created every time an event is fired.
The problem you are having is called the Producer/Consumer problem. And you can solve it easily using any of the ConcurrentCollections available.
Try something like this:
var queue = new ConcurrentQueue<string>();
var consume = true;
var producer = Task.Run(() =>
{
var input = Console.ReadLine();
while(!string.IsNullOrEmpty(input)
{
queue.Enqueue(input);
input = Console.ReadLine();
}
});
var consumer = Task.Run(() =>
{
while(consume) //So we can stop the consumer
{
while(!queue.IsEmpty) //So we empty the queue before stopping
{
stringres;
if(queue.TryDequeue(out res)) Console.WriteLine(res);
}
}
});
await producer;
consume = false;
await consumer;
Try using the Task Pattern Library instead of manually starting up threads. It is your friend.

c# sleeping thread problem

what is the problem in the code part below? Any ideas? I m sending command to my device through serial port. After each command the device will work for this command and then the other command comes for it and continues like this.
in Button Click event
{
function1();
Thread.Sleep(5000);
function2();
Thread.Sleep(5000);
function3();
}
I figured out if i erase second sleep and function3 from the code like below, it does both two function but if i want to continue like this way it does not do the third one.
in Button Click event
{
function1();
Thread.Sleep(5000);
function2();
}
works...
Thank you
You're blocking the UI thread. Don't do that. It means your UI can't update itself. Instead, set a System.Windows.Forms.Timer to fire in 5 seconds with the next function to call. Alternatively, do all of this in a different thread entirely (possibly using Sleep, possibly using another kind of timer to fire on a thread-pool thread) and use Control.Invoke/BeginInvoke to marshall back to the UI thread when you need to update the UI itself.
EDIT: Given your "answer", it seems that blocking the UI thread was only one of the problems - and getting the device to respond properly at all is a bigger problem. You shouldn't just rely on sleeping for a certain amount of time. You should detect when the device has completed the previous command. It's possible that it doesn't give any feedback, but that would be horrifically poor design. If at all possible, investigate how to read feedback from the device as to when it's finished (e.g. reading from the serial port!) and only start the next command when the previous one has finished. Depending on how you receive the feedback, you could use a blocking call on a non-UI thread, or use an asynchronous model to trigger things.
The BackgroundWorker might be a solution to solve the blocking of the UI.
Get rid of the Sleeps If the functions are creating their own threads, give them callback methods that trigger the next function after the first has finished.
As the code is presented there it is nothing wrong with it. It will:
Execute function 1
Sleep 5 seconds
Execute function 2
Sleep 5 seconds
Execute function 3
However since this is on a GUI event it will freeze the application while doing so. Consider spinning off the execution into a thread instead.
In .Net 4.0:
Task.Factory.StartNew(() => sendData());
In all .Net versions:
System.Threading.Thread myThread = new System.Threading.Thread(sendData);
myThread.IsBackground = true;
myThread.Start();
And then you have your sendData method:
private void sendData()
{
function1();
Thread.Sleep(5000);
function2();
Thread.Sleep(5000);
function3();
}
If you really need to do stuff in the GUI thread you can make it more responsive by regularly calling Application.DoEvents();, but this is not a good way of solving it.
Also remember that you can't access the GUI from other threads. See http://kristofverbiest.blogspot.com/2007/02/simple-pattern-to-invoke-gui-from.html for sample code on how to invoke the GUI thread from other threads.
Thank you guys. I solve it. The problem is i did not make thread sleep enough. 5000 ms do not enough for the second command.

Canceling Threads

I have an application that uses 20 threads. It's an email client that uses threads to mail from.
Currently the threads are created in the main thread. But I am wondering, what if I want to cancel the whole operation? The only way I can see of doing it is killing the main thread ... thus ending the program.
Would I have to create a thread that encapsulates the threads for mailing so I can kill the encapsulating thread?
I am currently using BackgroundWorker by the way and it's a WF application.
If you are using a BackgroundWorker then you already have all of the infrastructure you need to cancel the operation. Simply set WorkerSupportsCancellation to true on the BackgroundWorker, and invoke the worker's CancelAsync method when you want to cancel.
Obviously you have to write the worker code to honour the cancellation. You do this by checking the CancellationPending property of the BackgroundWorker.
MSDN has an example of using this property.
Note - I am a bit confused by the combination of BackgroundWorker and 20 threads; a BackgroundWorker only uses one thread by itself. Are you spinning off 20 BackgroundWorkers? If so, how do you ensure that they're properly disposed? If you need that much concurrency in a Winforms app then it's better to use asynchronous delegates or the Thread Pool.
If you are creating actual threads, one common way of implementing a cancellation flag is to use a ManualResetEvent. If you wait on this event with zero timeout, it acts as a thread-safe status flag. An example usage would be:
ManualResetEvent cancelEvent = new ManualResetEvent(false);
for (int i = 0; i < 20; i++)
{
ThreadPool.QueueUserWorkItem(s =>
{
// Do some work
if (cancelEvent.WaitOne(0, true))
return;
// Do some more work
// etc.
});
}
Then at some point later if you write cancelEvent.Set(), every worker will stop its work as soon as it hits the status check.

How do I communicate between multiple threads?

I'm writing a plug-in for another program which uses the native program to open a series of files to extract some data from. One problem I am having is the process takes a long time and I want to keep the user interface from hanging. Plus I also want to give the user the ability to cancel the process before it completes. In the past I've used a background worker for this type of thing, but in this case I don't think a BackgroundWorker will work.
To create a plug-in through the API I am using one can create a custom command by inheriting from an IAPICommand interface. This interface includes an Execute(Application app) method. The class is then instantiated and the Execute() method is called by the program when the user evokes the custom command in the program.
The Execute() method is passed a reference to the current Application object when it is called, and it is this application object that is used to open the files to extract data from. However, the application instance is not able to open a document when requested by a thread other the the original Execute() thread.
So typically the UI would exist on the main thread, and the time consuming data extraction would be performed on a secondary thread. However, in this case the data extraction must be performed on the main thread, and I need to create a secondary thread for the UI.
Here's a stripped down version of the code.
class MyCommand:IAPICommand
{
public void Execute(Application app) // method from IAPICommand
{
Thread threadTwo= new Thread(ShowFormMethod);
threadTwo.Start();
}
public void ProcessWidget(Widget w, Application app)
{
//uses an App to work some magic on C
//app must be called from the original thread that called ExecuteCommand()
}
//method to open custom form on a seperatethread
public void ShowFormMethod()
{
MyForm form = new MyForm();
form.ShowDialog();
}
}
Here is a flow chart that shows how I think this should ultimately work.
alt text http://dl.dropbox.com/u/113068/SOMLibThreadingDiagram.jpg
Does this diagram make any sense, and if so am I even taking the correct approach to solve this problem?
Once the main thread starts the UI thread I want it to wait for the user to either select widgets to process, or end the command by closing the form (the red figures on the diagram). How can I make the main thread wait, and how do I trigger it to continue either with processing or to continue to the end when the UI thread ends? I was thinking I could have the main thread wait on a Monitor lock. The UI thread would then populate a static list of Widgets to be processed, and then pulse the main thread to trigger the processing. The UI thread would also pulse the Main thread when the form is closed, and the main thread would know to continue to the end of the command if it was ever pulsed when the list of widgets to process was empty.
How do I allow the main thread to communicate the progress or completion of widget processing back to the UI thread (yellow arrows in the diagram)? Do I just used the BeginInvoke() method of the Form to do this?
How do I allow the UI thread to cancel the widget processing (green arrow in the diagram)? I think I could just setup a static Boolean flag that is checked before each widget is processed?
It's generally a bad idea to have multiple threads in your application that each create forms. It isn't impossible to make this work, but it's much harder than you think it will be because forms that are in a parent-child relationship send messages to each other, and when they do, the one sending the message blocks until the one receiving handles it.
Mix this in with the message passing or synchronization between threads that you are doing explicitly, and it's easy to end up with deadlocks. So, in general, you are better off making sure that you reserve your main thread for your user interface, and do all processing in other threads that have no UI.
If you conform to that design, then the background threads can use Control.BeginInvoke to pass messages to the UI thread without having to wait for the messages to be processed.
In addition to the other answers, I recommend that you use a callback method from ProcessWidget to pass progress back to the calling thread. To prematurely stop the worker thread, you can use the callback to return a halt signal to your worker thread if it updates the caller often enough. Or use a separate callback method to periodically check for go/no-go. Or set a (gasp!) global static flag that the worker periodically checks. Or call Thread.Abort on the worker thread and have it catch the ThreadAbortException to clean up any resources.
I assume that the host application is a WinForms app.
You need to save the SynchronizationContext from the original thread in your Execute method, then call its Send method to execute code on the host's UI thread.
For example:
class MyCommand:IAPICommand
{
SynchronzationContext hostContext;
public void Execute(Application app) // method from IAPICommand
{
hostContext = SynchronzationContext.Current;
Thread threadTwo = new Thread(ShowFormMethod);
threadTwo.Start();
}
public void ProcessWidget(Widget w, Application app)
{
//uses an App to work some magic on C
//app must be called from the original thread that called ExecuteCommand()
SomeType someData = null;
hostContext.Send(delegate { someData = app.SomeMethod(); }, null);
}
}
If you look at Java swing, it is a nice example of how to do this:
1) A main thread is responsible for handling all UI requests. This removes any race conditions from the app.
2) Any time any "work" is to be done, spawn a thread (or a thread pool) and do the work. Thus the main thread is not held up except for a few microseconds and the UI is completely responsive while whatever is going on.
3) In all languages there has to be a thread interrupt mechanism. In java you invoke .interrupt() on the thread, and the current running thread gets a InterruptedException thrown wherever it is executing. You job is to catch that exception, figure out if you are really interrupted (read javadocs for this part) and if you are just let yourself die (return out of the run method).
1 + 2 = unobtrusive client interaction
3 = killing threads
An alternative to 3 (if 3 is too complex) is to give the thread a method .kill(); the method sets a kill flag. When you are reading a buffer from the hard drive in a loop, check if the kill flag is set, if it is then break out of the loop, close handlers, and return out of the run method.
Edit: sorry forgot to mention progress report:
Your thread should have a publicly exposed thread-safe method of getting the "progress report" or rather a data structure containing information about progress. Your UI thread should periodically (say every .5 seconds) check the thread's progress report and update the UI's progress bar. And by UI thread checking I mean your widget that shows the progress makes a request to re-render with the latest information on a timer, until done.

WinForm Application UI Hangs during Long-Running Operation

I have a windows forms application
on which I need to use a for loop having a large number of Remote Calls around 2000 - 3000 calls,
and while executing the for loop, I loose my control on form and form controls, as it becomes a large process and some time it shows "Not Responding" but if I wait for a long it comes back again, I think I need to use some threading model for that, is there any idea, how can I proceed to solve the issue?
You need to perform the long running operation on a background thread.
There are several ways of doing this.
You can queue the method call for execution on a thread pool thread (See here):
ThreadPool.QueueUserWorkItem(new WaitCallback(YourMethod));
In .NET 4.0 you can use the TaskFactory:
Task.Factory.StartNew(() => YourMethod());
And in .NET 4.5 and later, you can (and should, rather than TaskFactory.StartNew()) use Task.Run():
Task.Run(() => YourMethod());
You could use a BackgroundWorker for more control over the method if you need things like progress updates or notification when it is finished. Drag the a BackgroundWorker control onto your form and attach your method to the dowork event. Then just start the worker when you want to run your method. You can of course create the BackgroundWorker manually from code, just remember that it needs disposing of when you are finished.
Create a totally new thread for your work to happen on. This is the most complex and isn't necessary unless you need really fine grained control over the thread. See the MSDN page on the Thread class if you want to learn about this.
Remember that with anything threaded, you cannot update the GUI, or change any GUI controls from a background thread. If you want to do anything on the GUI you have to use Invoke (and InvokeRequired) to trigger the method back on the GUI thread. See here.
private voidForm_Load(object sender, EventArgs e)
{
MethodInvoker mk = delegate
{
//your job
};
mk.BeginInvoke(callbackfunction, null);
}
private void callbackfunction(IAsyncResult res)
{
// it will be called when your job finishes.
}
use MethodInvoker is the easiest way.
Obviously, you need to use background threads. I suggest you read this free e-book.

Categories

Resources