I have an application which uses 1 Main Window and in turn this window has 5 UserControls which are created using a Ribbon Control.
On one of the user controls I kick off a thread :
if (AmtMembersWithEmail > 0)
{
DispatcherHelper.UIDispatcher.Invoke(new Action(() =>
{
max = 100;
Messenger.Default.Send<ShowProgressWindowMessage>(
new ShowProgressWindowMessage(this));
Progress = 0;
Thread.Sleep(1000);
}));
So this thread kicks off and reports progress back to the main window, during this time, as the thread executes the user cannot access the controls or do anything else within the application, from reading up on the dispatcher this is normal as it must use the single UIThread which allows the user to interact with controls on the UI. ( Using Galasoft MVVM 开发者_如何转开发light by the way! )
The window that displays reporting the progress has a command which binds to a relay command in my viewmodel: Extract from XAML progress window is below:
<tk:LoadingAnimation Grid.Row="0" DataContext="{Binding}"/>
<ContentControl Visibility="{Binding CanBeAborted,
Converter={StaticResource VisibilityConverter}}" >
<Hyperlink Command="{Binding AbortCommand}">cancel</Hyperlink>
</ContentControl>
Is there any way to use the dispatcher to allow the thread to run in the background? or will the user just have to wait until the operation completes?
To add, the work the thread is actually doing is looping customer data, creating attachments ( invoices ) and creating an email object for each customer before finally looping that new email collection and sending each email individually to the customer...
Any help would be greatly appreciated....
I am not completely clear whether you have your processing logic in the User Control (i.e. Code Behind), or in your ViewModel. If it's in your ViewModel, then I think you're on the right track.
Instead of using the dispatcher, I suggest spinning a BackgroundWorker:
public void DoWork()
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (sender, e) =>
{
//Processing Logic here
};
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Work_Completed);
worker.RunWorkerAsync();
}
void Work_Completed(object sender, RunWorkerCompletedEventArgs e)
{
}
This will not run on the UI thread, therefore your User Control should be responsive. Also, as Will as suggested, DO NOT TERMINATE THREADS. Your Abort logic should gracefully exit the loop inside of your processing logic, cleaning up the resources it used and performing any undo work you need done.
精彩评论