Displaying a "Please Wait" Dialog for a Non-Thread Safe task - c#

I am using 3rd party library and some of the functions of the library take a long time to execute so I want to display a "Please Wait" dialog while the functions are busy.
Normally I would do something like this:
Thread longTask = new Thread (new ThreadStart(LongTask));
longTask.IsBackgroud = true;
longTask.Start();
pleaseWaitForm = new PleasWaitForm ("Please wait for task to complete");
pleaseWaitForm.ShowDialog();
void LongTask()
{
// Do time consuming work here
pleaseWaitForm.CanCloseFlag = true;
}
Unfortunately the 3rd party library is not thread-safe. Any workarounds? Is there any way of managing the Dialog Box as a background task?

I think you are misunderstanding what "thread safe" means. If you are going to be calling methods/properties of your 3rd party component only from single thread, the component does not have to be thread safe. See this article.
Furthermore, I would suggest you use a background worker class in this case.
HTH

You pretty much need to build your own dialog box.
One option is to poll your completed flag in a timer or the like.
Yet another option is to let the form "own" the task and use a BackgroundWorker for progress and completion notification.

Suppose you have a method, LongTask, and it is not thread safe. If that method is running and it does not need any shared variables, then you can simply wrap it around a BackgroundWorker and update the "please wait" screen the moment the task finishes.
If a certain method is not thread safe, that can still mean it is safe to use it in a thread, it just depends whether it runs multiple times asynchronously (danger!) or synchronously (not a problem).

Related

How to call Same event Handler with multiple class object in Windows form C# [duplicate]

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.

Thread Termination suggestion required

I am using BackgroundWorker for processing a long running external operation. However the user have option to cancel the background operation. Since my custom BackgroundWorker supports Thread.Abort(), all I am doing is BackgroundWorker.Abort() when user triggers Cancel from main thread.
But the thread is not actually terminating, it is still completing the external process. Is there any way I can terminate a thread instantly.
I do not have control on the external processing, so cannot send any flag for approach like while (checkThreadCancelled){}.
Below is my pseudo code.
Any help?
AbortableBackgroundWorker _bgWorker;
void MainThreadFunc()
{
_bgWorker = new AbortableBackgroundWorker();
_bgWorker.DoWork += new DoWorkEventHandler(bg_DoWork);
_bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler
( bg_RunWorkerCompleted );
_bgWorker.WorkerSupportsCancellation = true;
_bgWorker.RunWorkerAsync();
}
void bg_DoWork()
{
//Call external dll function for processing
}
void bg_RunWorkerCompleted()
{
//Process completed code
}
void CancelBgProcess()
{
if(_bgWorker != null)
_bgWorker.Abort();
}
The Abort method relies on worker thread cooperating with it. Ultimately it causes the CLR to throw an exception indicating that the thread is to abort, which the thread is free to deal with as it pleases.
As your worker thread is executing something in a DLL, the CLR isn't in control and therefore it does not have the option to throw an exception.
You have the option of using the Win32 TerminateThread API, but doing so is severe and may or may not lead to corruption within your process. TerminateThread is not really an option that you should ever choose.
Since you cannot modify the library that you are calling, you are left with two options. The first and easiest approach, lower the priority of the background thread and ignore the fact that it continues to run after cancellation.
The second is to launch your background operation in a separate process rather than thread. At which point, you may terminate the entire process if the operation is cancelled. If you go this route, you will need to pick some form of IPC to communicate the input and output parameters of the library.
Tasks and CancellationTokens ultimately will not help you in this situation as you will end up in the same place: executing library code that will not cooperate with you in order to be cancelled.
You don't want to use Thread.Abort, it is typically considered bad practice. There are many questions asked on SO that provide some very good explanations. For example: Timeout Pattern - How bad is Thread.Abort really?
Try looking at Tasks and CancellationTokens. See this MSDN article: http://msdn.microsoft.com/en-us/library/dd997396.aspx
Try this:
if (_bgWorker.IsBusy)
{
_bgWorker.WorkerSupportsCancellation = true;
//To cancel the Thread if Closing the Application
//while the Background Thread Worker is Still running on Background.
_bgWorker.CancelAsync();
}
It will stop the current thread process and will cancel the ongoing operation on that thread.
May be it helps you

Blocking with Task?

I try to use tasks in my application like this :
Task test;
test = Task.Factory.StartNew(() => general.Login(loginName, password));
MyTextBox.Text = "test text";
It will be the UI thread that makes this call and I need it to be blocked until the worker thread returns from the service but I do not want the UI to freeze.
I could use a ContinueWith but this will split my login method and this makes it harder to follow. I do also need the main UI thread to run the rest of the code in this method.
How do I solve this?
This is precisely the problem that async in C# 5 solves. For the moment, you basically have to split your code. It's a pain, but that's the way it is. (Your description is slightly off, by the way - you don't want to block the UI thread... you want to "not perform the second part of your logic" until the worker thread returns. Not quite the same thing :) (You may also want to disable some other bits of the UI, but we can't tell for sure.)
It's worth getting a head start on the async feature - see the Visual Studio async home page for a lot of resources.
There is no way to wait for a thread without blocking the waiting thread. What you can do is something like:
fire task
do some other task
wait for task // hopefully the task finished by now

Windows Application gets hanged when using a background worker process

In my application i am sending emails of bigger size (> 2.5 Mb). Now till the emails are being sent, the application is in hanged up state (mouse cursor is of busy state).
One of my friend suggested to use background worker that "could" display message something like "Please wait...Sending email". I have no idea as to how to use the background worker process. Please guide me
Or, if there is any other quicker/easier alternative, i would appreciate the inputs
You don't want to use a separate process - you want to use a different thread.
The work of sending the email shouldn't be done in the UI thread, as that will prevent it from updating. However, you may want to disable parts of your UI while the email is being sent, depending on your app.
When it comes to doing the email work in the background, you could create a new thread explicitly, use the thread pool, or create a BackgroundWorker. You probably want to use Control.Invoke or Control.BeginInvoke to marshal a delegate invocation back to the UI thread when the email has been sent. Personally I would probably use a thread directly for this - it sounds like it'll take a reasonable time, and my guess is that you won't be able to report meaningful progress (which is the main task that BackgroundWorker makes easy). EDIT: As per comments, BackgroundWorker also marshals exceptions to the UI thread, which you may find useful.
So something like:
public void SendEmailButtonClicked(object sender, EventArgs e)
{
// Make any changes to the UI here to disable whatever you want
new Thread(SendEmail).Start();
}
private void SendEmail()
{
// Do the sending of the email here (this is in the non-UI thread)
// Then afterwards, possibly in a finally block
Action action = EmailSent;
this.BeginInvoke(action);
}
private void EmailSent()
{
// Back in the UI thread, do whatever you need to indicate
// success/failure, re-enable disabled parts of the UI etc
}
The BackgroundWorker documentation contains some pretty good examples which should help to get you started.
A background worker is perfect for this. It allows you to monitor progress quite easily and can Marshall back to the UI thread easier than a standard thread. Some links after some google fu:
http://justins-fat-tire.blogspot.com/2010/05/c-using-background-worker.html
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
http://www.dotnetperls.com/backgroundworker
If you don't want your UI to hang while waiting for long processes you have to use a thread. BackgroundWorker is a good implementation of this that provides hooks for you to use to report progress, allow the user to abort the process etc.
There are plenty of questions about the BackgroundWorker here on Stack Overflow or check the MSDN documentation.
I would try to use BackgroundWorker control. Refer below links
Designing an Interface for BackgroundWorker
http://www.albahari.com/threading/part3.aspx
http://www.agiledeveloper.com/articles/BackgroundWorker.pdf
Look at this threading tutorial:
http://msdn.microsoft.com/en-us/library/aa645740%28v=vs.71%29.aspx
Basic idea is to have your mouse click event spawn a new thread that will take care of sending the email.

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