WPF C#长时间运行

时间:2011-10-03 21:21:03

标签: c# wpf multithreading controls

基本上我在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线程上,并且应用程序再次挂起:/

关于在这种情况下我能做些什么的任何建议? 非常感谢

4 个答案:

答案 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。