Reputation: 21
I am trying to create a load window which will have a progress bar and display this while the background worker does some time intensive work. Unfortunately, this load window only partially loads then freezes until the background work is completed. How can I fix this so that the load window does not conflict with the background processes?
A visual example: https://i.sstatic.net/JHXvv.png
lw = new LoadWindow();
lw.Show();
worker.DoWork += delegate(object s, DoWorkEventArgs args)
{
/*Program-specific code*/
string theDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); /* get the folder location of the exe */
string filePath = theDirectory + "\\export.xml";
if (!File.Exists(filePath))
{
FileStream f = File.Create(filePath);
f.Close();
}
FileStream fileStream = File.Open(filePath, FileMode.Open);
fileStream.SetLength(0);
fileStream.Close();
FileStream fsWrite = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.None);
StreamWriter sw = new StreamWriter(fsWrite);
Dispatcher.Invoke(new Action(delegate() {
/*Program-specific code*/
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo("cmd.exe", "/C svn log " + FolderPath.Text + " -v --xml");
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
using (System.Diagnostics.Process process = Process.Start(startInfo))
{
using (StreamReader reader = process.StandardOutput)
{
string outStr = reader.ReadToEnd();
sw.Write(outStr);
sw.Close();
fsWrite.Close();
reader.Close();
process.WaitForExit();
}
}
TicketIDChanged(sender, new TextChangedEventArgs(e.RoutedEvent, new UndoAction()));
}), DispatcherPriority.Background);
};
worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
{
lw.Hide();
};
worker.RunWorkerAsync();
Upvotes: 1
Views: 166
Reputation: 1
With the .NET 4.0 release, we got the Task Parallel Library (TPL) which provided APIs for performing Parallel and Task Based Asynchronous Operations. The TPL provides classes like Task and Parallel which were used for performing asynchronous programming and parallel operations respectively. In .NET 4.5 with C# 5.0 we got the async and await keywords for representing asynchronous methods. In WPF, we can make use of the Task class for creating responsive and interactive applications.
Upvotes: 0
Reputation: 273701
You are using Dispatcher.Invoke()
to run a big chunk of code (from StartProcess to WaitForExit) on the GUI thread. Yes that will block.
And I don't see the reason for the Invoke. Running a process is well suited for running in DoWork()
.
The only part that needs syncing is the TicketIDChanged()
at the end. Do that with Dispatcher.Invoke()
or move it to the Completed event.
Upvotes: 1
Reputation: 5795
By using Dispatcher.Invoke()
you are delegating all the work within the delegate onto the UI-Thread. If this is a time intensive operation it'll get stuck here.
Try to use Dispatcher.Invoke()
for updating UI states only. If this isn't easily accessible, try to refactor your code and add multiple invocations.
You can also set worker.WorkerReportsProgress = true
and use the worker.ReportProgress(int percent, object args)
method to update a simple progress bar on your loading screen. The dispatching will then be handled by the BackgroundWorker.
Try to invoke only the TickedIDChanged
-method, for example.
Upvotes: 1
Reputation: 4581
Looks like you are doing the work on the UI thread not background. I might be wrong because im not 100% sure what the background priority means. However, what i would advise you try is to not do the async work inside a dispatcher invoke... And if part of the async work is to assigment to something on the UI thread then do just the assignment in a dispatcher invoke inside the completed handler along with the hide like you do.
Upvotes: 0