基本上我在wpf中遇到c#线程问题以及如何正确使用它们。
起初,由于长时间运行,我碰到了我的应用程序挂起。在研究了如何解决这个问题后,我决定使用Dispatcher BeginInvoke方法并将运行操作放在自己的线程上。但是,必须发送到UI线程的代码量太多而无法发挥作用。
以下是我正在做的导致悬挂的简化版本:
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);
}
}
}
如您所见,操作中的大多数处理都包含使用控件。因此,必须异步调度它们到UI线程。执行此操作后,基本上所有操作都在UI线程上,并且应用程序再次挂起:/
关于在这种情况下我能做些什么的任何建议? 非常感谢
答案 0 :(得分:1)
在紧密循环中创建如此多的可视对象肯定是迟钝的。也许您可以尝试将其分为两个阶段。在紧凑的循环中,您只需为图像创建占位符。说一个带填充颜色的矩形,以指示将来图像的显示位置。
然后在另一组线程中,您实际加载图像的内容并设置绑定。这样,用户界面始终保持响应。用户立即看到占位符,然后看到实际图像在实时加载时替换占位符。您可以在网页上看到这一点,占位符在下载时会显示实际内容。
答案 1 :(得分:0)
通过在UI线程上运行所有内容,您当然不会利用现代处理器的所有内核。
看起来您正在处理来自UI线程的多个图像。我怀疑图像处理是CPU密集型任务,而不是代码示例中暗示的其他项目。如果是这种情况,请考虑在许多不同的线程上进行图像处理,并让UI线程执行每个工作线程完成时需要执行的操作。
如果可以使用.NET 4,Task Parallel Library可以很容易地使用线程。我发现BlockingCollection对于协调UI线程和工作线程之间的工作非常有用。我提供的链接中有很好的代码示例。
答案 2 :(得分:0)
以下是示例,异步创建大量UI对象:
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);
}
}
答案 3 :(得分:0)
您可以确保UI线程所需的处理在其空闲时间内处理,即当它不处理事件等时。
这是通过在分派操作时使用优先级设置System.Windows.Threading.DispatcherPriority.SystemIdle
来完成的。
This link aught to provide the details you need(标记具有长时间运行计算的单线程应用程序)
这肯定会降低处理完成的速度,但它可以让您在处理过程中保持功能齐全的UI。