WPF C# Long running operation
Basically i am having problems with c# threads within wpf and how to use them properly.
At first i bumped into my app hanging due to a long running operation. 开发者_如何学JAVAAfter researching how to resolve this, i decided to use the Dispatcher BeginInvoke method and put the running operation on its own thread. However the amount of code that has to be sent to the UI thread is too much to make any difference.
Here is a simplified version of what i am doing that causes the hanging:
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 100; j++)
{
for (int k = 0; k < 100; k++)
{
Image image = new Image();
// ... Do stuff with image here
Binding binding = new Binding();
// ... Bind some properties to the image
// Add the image to a list and a canvas
List.Add(image);
SomeCanvas.Children.Add(image);
}
}
}
As you see most of the processing in the operation consists of using controls. Therefore they have to be dispatched to the UI thread asynchronously. After doing this, basically all of the operation is on the UI thread and again the application hangs :/
Any suggestions on what i can do in this situation? Many Thanks
Creating so many visual objects in a tight loop is bound to be sluggish. Perhaps you could try splitting this into two phases. Inside your tight loop you merely create a placeholder for the image. Say a rectangle with a filled colour to indicate where the image will be shown in the future.
Then in another set of threads you actually load the contents of the images and setup the bindings. That way the user interface stays response at all times. The user sees placeholders immediately and then sees the actual images replace the placeholders as they are loaded in real time. You see this all the time on web pages where the placeholders get filled with the actual content when it is downloaded.
You're certainly not leveraging all of the cores of a modern processor by running everything on the UI thread.
It looks like you're processing multiple images from your UI thread. I suspect that the image processing is the CPU intensive task, not the other items hinted at in your code sample. If that's the case, consider doing the image manipulation on a number of different threads and having the UI thread do what it needs to do when each worker thread completes.
If you can use .NET 4, the Task Parallel Library makes it very easy to work with threads. I find the BlockingCollection very useful for coordinating work between the UI thread and worker threads. There are good code examples in the link I provided.
Here's the sample, creating a large number of UI objects asynchronously:
public partial class Window1 : Window
{
public delegate void CreateCanvasHandler(Grid parent, int index);
public Window1()
{
InitializeComponent();
int count = 10000;
this.TestCreateAsync(count);
}
private void TestCreateAsync(int count)
{
for (int i = 0; i < count; i++)
{
//check the DispatecherOperation status
this.LayoutRoot.Dispatcher.BeginInvoke(new CreateCanvasHandler(this.CreateCanvas),
DispatcherPriority.Background,
new object[2]
{
this.LayoutRoot,
i
});
}
}
private void CreateCanvas(Grid parent,
int index)
{
Canvas canvas = new Canvas()
{
Width = 200,
Height = 100
};
canvas.Children.Add(new TextBlock()
{
Text = index.ToString(),
FontSize = 14,
Foreground = Brushes.Black
});
Thread.Sleep(100);
parent.Children.Add(canvas);
}
}
You may ensure that the processing required to be done by the UI thread is handled in its idle time, i.e. when it is not processing events etc.
This is done by using the priority setting System.Windows.Threading.DispatcherPriority.SystemIdle
when dispatching an operation.
This link aught to provide the details you need (label A Single-Threaded Application with a Long-Running Calculation)
This will surely decrease the rate at which your processing completes, but it will allow you to maintain a fully functional UI whilst processing.
精彩评论