DoEvents vs anything else --> for long COM operation - c#

I have a WPF program where my model need to load a "Out-of-Proc" (.exe) COM component in order to achieve some validations when a user make an action on the UI. I'd like to inform the user that a long action will take place to let him know that the application is busy, not just frozen. But any action on the UI does occur after the COM action is completed.
I think that any COM communication should be done on the main UI thread. It eliminates any solution that would run on another thread than the main (UI) thread.
I tried many options without success:
MSDN Dispatcher.PushFrame (DoEvents)
StackOverflow HCL (PushFrame)
Jason programming Blog (PushFrame)
I can't see how I can achieve a synchronous action from a model where I would need to refresh the UI.
My action has a property "IsLoading" that I subscribe from my view and where I try to update the UI according to its state but it seems that is not possible in WPF ???
Any other suggestions ?
Can I use async/await and do my COM action from another thread running another dispatcher (kind of complex) and will loose required synchronicity (user need results of COM operation to continue its work) ?
Mainly for Blindy...
Some clearer explications (more details about required synchronicity):
When a user click on a TreeView item, I load a grid then need to verify that data entered in the grid is still valid. To do validation, I need to load an application through COM and automate it to load a document, then parse it and verify the data in the grid (in the Model of the Grid in the view). That takes 10 seconds.
If I do that on another thread, then user can do an action to select to add a new row in the grid which still depends on the same COM application loaded with the previous document. I still need to wait for the application to load. It is a synchronous action. My application depends on that COM application with its loaded document to be in valid state for user to take more actions. But I need to give user some feedback on what I’m doing (start COM app and load on document). Doing COM action on another thread just report the problem later but do not solve the fact that user need to wait that the action would complete. I think I need to (force) update my WPF app but can’t find any (twisted) way to do it.

[UPDATE] As the OP has updated the question and specified he's using out-of-proc COM objects, the custom STA thread plumbing described below doesn't make sense. Now, a simple await Task.Run(() => { /* call the out-of-proc COM */}) is enough to keep the UI responsive. Kudos to #acelent for clarifying this point.
Recently I answered a related question: StaTaskScheduler and STA thread message pumping.
The solution was to create and use STA COM objects on a dedicated background STA thread which provides both message pumping and thread affinity for those COM objects.
I'd like to show how ThreadWithAffinityContext can be used in your case, with async/await:
dynamic _comObject = null;
ThreadWithAffinityContext _staThread = null;
// Start the long-running task
Task NewCommandHandlerAsync()
{
// create the ThreadWithAffinityContext if haven't done this yet
if (_staThread == null)
_staThread = new ThreadWithAffinityContext(
staThread: true,
pumpMessages: true);
// create the COM Object if haven't done this yet
if (_comObject == null)
{
await _staThread.Run(() =>
{
// _comObject will live on a dedicated STA thread,
// run by ThreadWithAffinityContext
_comObject = new ComObject();
}, CancellationToken.None);
}
// use the COM object
await _staThread.Run(() =>
{
// run a lengthy process
_comObject.DoWork();
}, CancellationToken.None);
}
// keep track of pending NewCommandHandlerAsync
Task _newCommandHandler = null;
// handle a WPF command
private async void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
try
{
// avoid re-entrancy (i.e., running two NewCommandHandlerAsync in parallel)
if (_newCommandHandler != null)
throw new InvalidOperationException("One NewCommandHandlerAsync at a time!");
try
{
await _newCommandHandler = NewCommandHandlerAsync();
}
finally
{
_newCommandHandler = null;
}
}
catch (Exception ex)
{
// handle all exceptions possibly thrown inside "async void" method
MessageBox.Show(ex.Message);
}
}
The fact that we have offloaded the lengthy process _comObject.DoWork() to a separate thread doesn't automatically solve the other common UI-related problem:
How to handle the UI when the lengthy background operation is pending?
There is a number of options. E.g., you can disable the UI elements which fire NewCommand_Executed event, to avoid re-entrancy, and enable another UI element to allow the user to cancel the pending work (a Stop button). You should also provide some progress feedback, if your COM object supports that.
Alternatively, you can display a modal dialog before staring the long-running task and hide it when the task has completed. As far as the UI usability goes, modality is less desirable, but it's very easy to implement (example).

You can create and use COM objects on any thread, the marshaller will take care of running it on a background thread if your application uses the STA threading model. There's no need to funnel every call through the main UI thread.
As to your last question in comments, since you'll be running this on a background thread, you of course need to synchronize like usual with lock and Invoke the result back on the main thread when done. This is nothing specially related to COM, it's just how Windows threading works.
In short, stop using the UI thread for heavy duty, non-UI related work.

I used this once for WPF so as to force the screen to re-Paint :
I used auto-translation from VB so I hope it's correct
private Action EmptyDelegate = () => { };
[System.Runtime.CompilerServices.Extension()]
public void Refresh(UIElement uiElement)
{
uiElement.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, EmptyDelegate);
}

Related

How to retrieve information in a second thread with a Windows Forms C# Application

I have an usual C# Windows Forms Application with one Form and several TextBoxes / Labels which runs (how I understand) in its own thread. (Win 7 64 / VS 2008 / Net 2).
Now I want to start a second thread while my base application stays in the first thread.
The second thread shall retrieve some system information and input it into the Labels while my user is still able to fill in the TextBoxes while the information is going to be retrieved by the second thread. So the advantage would be by my understanding, that the user has not to wait until retrieving information is completed and the main application would not hang in that time.
Let's say I want this code to be executed in a second thread which starts in the Form_Shown event:
Label1.Text = GetInternetIP();
try
{
Label2.Text = System.Net.Dns.GetHostEntry(Label1.Text).HostName.ToString();
}
catch{MessageBox.Show("Fatal Error."); Process.Start("shutdown.exe", "-r -t 2"); this.Activate(); SendKeys.Send("%{F4}");}
I would be grateful for a detailed description on how to setup a "new thread". I am a newbie but I would like to learn something new and optimize (speed up) my very first applications.
The Label1 and Label2 are in the main thread on the main form (Form1). So I have to get the retrieved information there.
in dealing with Windows forms the UI can only run on one thread, then it will create background threads the background threads retrieve the data and then pass it to the single UI Thread. This is also how it works in WPF.
take a look here on how to do this
http://msdn.microsoft.com/en-us/magazine/cc300429.aspx
You should never access your UI components from code running on another thread. In fact, you shouldn't access anything from multiple threads unless those things are explicitly thread-safe (or you access them in a thread-safe manner).
In your example you are saying you want to fetch information which takes some time. In your case the programming model you want is to have your main thread call an asynchronous function to retrieve that information, and it should signal your main thread when the information is ready.
There are a lot of different ways to implement multithreaded programming in C#, but here is one example:
public Task<IPAddress> GetInternetIP()
{
return Task.Factory.StartNew(() =>
{
IPAddress ip;
// do some work to get the IPAddress
return ip;
});
}
private void Form_Load(object sender, EventArgs e)
{
GetInternetIP().ContinueWith(ip =>
{
Label1.Text = ip.ToString();
}, TaskScheduler.FromCurrentSynchronizationContext());
}
In this case what you're doing is executing a System.Threading.Tasks.Task which will handle the multithreading for you. And you're telling it to continue execution with a method on the current thread. That method is passed the return value of the task (in this case an IPAddress object).
to access user controls that are on the main thread from your background thread you only need to use BeginInvoke against the controls you want to populate. This is an article that fully explains how to do so along with the ins and outs of doing so.
http://weblogs.asp.net/justin_rogers/pages/126345.aspx
The three answers which I received brought me nowhere or have not worked, so I found it out myself much later: I used the Backgroundworker-Control to achieve what I wanted. In the "Completed"-Event of the Backgroundworker I can access the UI and transfer the information to the form attached to my application. What helps me a second thread if my UI is locked for that second thread, so Backgroundworker is the best for me to go and self-explaining.

How do I make my application wait for my UI to refresh?

Without using extra threads I would simply like to display a "Loading" label or something similar to the user when a large amount of data is being read or written. If I however attempt to modify any UI elements before calling the IO method, the application freezes for a while and then displays the "Loading" message after all the work is already done. This obviously doesn't help. How can I ensure that any UI changes are applied and visible before calling the IO method?
DataSet ds = STT_Import.ImportExcelToDataSet(filePath);
bool result = false;
if (ds != null)
{
int cellCount = ds.GetTotalCellCount();
if (Popup.ShowMessage(string.Format("Your file contains {0} cells. Inserting data will take approximately {1} seconds. Do you want to continue?",
cellCount, CalculateTime(cellCount)), "Confirm", MessageType.Confirm) == MessageBoxResult.Yes)
{
// Tell user the application is working:
StatusLabel.Content = "Writing to database...";
// Do actual work after user has been notified:
result = DB.StoreItems(_currentType, ds);
}
}
I tried looking for answers but couldn't find anything that answered my specific question, so I'm sorry if the question has been asked before.
When working with WPF, you can use the Dispatcher to queue commands on the UI thread at different DispatcherPriorities
This will allow you to queue your long-running process on the UI thread after everything in the DispatcherPriority.Render or DispatcherPriority.Loaded queues have occurred.
For example, your code may look like this:
// Tell user the application is working:
StatusLabel.Content = "Writing to database...";
// Do actual work after user has been notified:
Dispatcher.BeginInvoke(DispatcherPriority.Input,
new Action(delegate() {
var result = DB.StoreItems(_currentType, ds); // Do Work
if (result)
StatusLabel.Content = "Finished";
else
StatusLabel.Content = "An error has occured";
}));
It should be noted though that its usually considered bad design to lock up an application while something is running.
A better solution would be to run the long-running process on a background thread, and simply disable your application form while it runs. There are many ways of doing this, but my personal preference is using the Task Parallel Library for it's simplicity.
As an example, your code to use a background thread would look something like this:
using System.Threading.Tasks;
...
// Tell user the application is working:
StatusLabel.Content = "Writing to database...";
MyWindow.IsEnabled = False;
// Do actual work after user has been notified:
Task.Factory.StartNew(() => DB.StoreItems(_currentType, ds))
// This runs after background thread is finished executing
.ContinueWith((e) =>
{
var isSuccessful = e.Result;
if (isSuccessful)
StatusLabel.Content = "Finished";
else
StatusLabel.Content = "An error has occured";
MyWindow.Enabled = true;
});
You are trying to solve the problem in the wrong manner. What you should be doing here is run the time-consuming task in a worker thread; this way, your UI will remain responsive and the current question will become moot.
There are several ways you can offload the task to a worker thread; among the most convenient are using the thread pool and asynchronous programming.
It is provably impossible to keep your UI responsive without utilizing additional threads unless your database provides an asynchronous version of the method you're using. If it does provide an asynchronous version of the method then you simply need to use that. (Keep in mind that async does not mean that it's using any other threads. It's entirely possible to create an asynchronous method that never uses additional threads, and that's exactly what's done with most network IO methods.) The specifics of how to go about doing that will depends on the type of DB framework you're using, and how you're using it.
If your DB framework does not provide async methods then the only way to keep the UI responsive is to perform the long running operation(s) in a non-UI thread.
The Approach you are using is not efficient way so I would suggest to go with Async Programing or threading
Async programming:
Visual Studio 2012 introduces a simplified approach, async programming, that leverages asynchronous support in the .NET Framework 4.5 and the Windows Runtime. The compiler does the difficult work that the developer used to do, and your application retains a logical structure that resembles synchronous code. As a result, you get all the advantages of asynchronous programming with a fraction of the effort. Support .Net framework 4.5
It will save your time to implementing System .Threading and very efficient for the task same as your where we have to wait for some operation
http://msdn.microsoft.com/en-ca/library/vstudio/hh191443.aspx
http://go.microsoft.com/fwlink/?LinkID=261549
or
Threading:
The advantage of threading is the ability to create applications that use more than one thread of execution. For example, a process can have a user interface thread that manages interactions with the user and worker threads that perform other tasks while the user interface thread waits for user input.Support .Net fremework 4.0 or Older
http://msdn.microsoft.com/en-us/library/aa645740%28v=vs.71%29.aspx
If you don't want the UI to be responsive I use a busy indicator.
There are prettier cursors - this is an in house application.
using (new WaitCursor())
{
// very long task
Search.ExecuteSearch(enumSrchType.NextPage);
}
public class WaitCursor : IDisposable
{
private Cursor _previousCursor;
public WaitCursor()
{
_previousCursor = Mouse.OverrideCursor;
Mouse.OverrideCursor = Cursors.Wait;
}
#region IDisposable Members
public void Dispose()
{
Mouse.OverrideCursor = _previousCursor;
}
#endregion
}

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.

Separation of GUI and logic in different threads in a Windows Form application

In a Windows Forms application I want to separate the GUI from the logic. The user requests are complex and involve communications so I don't want it to depend on the GUI thread. The structure should be something like:
GUI -----> splash screen ---------> User Form --------------> ...
| #
| create Manager thread | Show this Form
# |
Manager -----> Check user type -------> Wait for user command --> ...
Which are your advices, guidelines or patterns for a design like this one? Is it the correct choice? Thank you!
EDIT
The Manager thread should control the GUI and not in reverse. Moreover, the Manager thread should live during all the application time.
Traditionally work like this is done using a BackgroundWorker
Basically it is a simple class that gives you the ability to perform a function on a worker thread and then will automatically invoke back to the UI thread after that function is complete. During the time that the function is being run the UI is unblocked and can display a progress message, or process other user input (cancel for example).
The result is similar to your pattern, but a separate thread is created and destroyed (well, there is pooling really...) for each task.
UI thread ---> Show splashscreen------------------->Show window-------
| |return to UI |
| create background worker | |
-> Process user ------------ ->Perform query etc.
Okay, based on your comment:
You can use a pattern like that, it is a simple case of eventing. Give the UI access to your manager so that it can perform a method call on it and register for events when the task is completed (this link shows the two major patterns for async operations in .NET). Inside the manager you'll need to maintain a list of tasks that can be performed in sequence on the single thread and ensure that the events that are called to return the results to the UI are properly invoked so that are run on the main UI thread (basically recreate the background worker pattern).
I'm not sure what you are hoping to gain by doing this, is there a reason the application needs to be limited to two threads? Are you concerned about the cost of creating backgroundworkers? Do you need some kind of query queue system? The examples in the diagram in your question don't seem to require the complexity of this kind of pattern.
You should use a background worker to complete your task.
It has events that will be very handy. DoWork and RunWorkerCompleted, which will come in very handy.
You can also try using Threads, They will look something like this:
(Bear in mind, when you use Threads, if you want to do any work with the UI Thread, you must Invoke(), otherwise you will received a CrossThreadException)
private delegate void MyFunctionCaller();
//This will set up your worker thread and set it off
private void SetThreadToDoWork()
{
ThreadStart threadStart = new ThreadStart(DoWork);
Thread MyThread = new Thread(threadStart);
MyThread.Start();
ShowSplashScreen();
}
private void DoWork()
{
DoMyWork();
WorkCompleted();
}
private void WorkCompleted()
{
if (InvokeRequired == true)
{
MyFunctionCaller InvokeCall = delegate { WorkCompleted(); };
Invoke(InvokeCall);
}
else
{
//Back to the UI thread now.
}
}
OPs Edit
You can create the thread wherever you like, once it has started you can have it completing several functions. But keep in mind that you need to Invoke() if you want to complete any work that the UI Thread can only complete otherwise you will get a CrossThreadException.
I've developed a similar project. GUI launch the manager on a different Thread.
Manager have some method to get commands from the GUI.
GUI is listening to Manager's events, so it's updated only when Manager raise up an event.
To avoid crossthreading, i used to "Invoke" methods

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