尝试运行无限循环线程时WPF UI挂起

时间:2012-10-01 17:42:39

标签: c# wpf multithreading

所以我的问题是,当我为我的wpf应用程序设置一个无限的线程时,ui挂起但当然这不是我对多线程应用程序的期望。

继承我的代码

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        System.Threading.Thread thread = new System.Threading.Thread(
            new System.Threading.ThreadStart(
                delegate
                {
                    Dispatcher.Invoke(DispatcherPriority.Normal,
                        new Action<Polyline>(ChangePoints), polyline);
                }));
        thread.Start();
    }

    private void ChangePoints(Polyline p)
    {
        while (true)
        {
            Random random = new Random();
            p.Points.Clear();
            for (int i = 0; i < 500; i += 10)
            {
                p.Points.Add(new Point(i, random.Next(1, 300)));
            }
        }
    }
}


<Window x:Class="ClientSide.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="300" Width="500">
    <Canvas x:Name="canvas" Background="#00FFFFFF">
        <Polyline x:Name="polyline" Stroke="DarkGreen" StrokeThickness="3" />
    </Canvas>
</Window>
你能告诉我这里有什么不对吗?

1 个答案:

答案 0 :(得分:4)

  你能告诉我这里有什么不对吗?

您创建一个新线程,但随后立即使用Dispatcher将线程的工作封送到UI线程。这将导致它完全在UI线程上运行。

由于您正在执行无限循环,这会导致它无限期地锁定UI线程。

要纠正,您需要切换逻辑。不要将调用编组回整个方法的UI线程,而是构建点,并仅编组在循环中设置p.Points的调用。您可能还需要在那里创建某种形式的延迟,因为它将尽可能快地运行(给定当前代码),这可能会使UI无响应。

尝试以下内容:

public MainWindow()
{
    InitializeComponent();
    System.Threading.Thread thread = new System.Threading.Thread(
        new Action(() => ChangePoints(polyline)));
    thread.Start();
}

private void ChangePoints(Polyline p)
{
    // Create once and reuse
    Random random = new Random();

    while (true)
    {
        PointCollection points = new PointCollection();
        for (int i = 0; i < 500; i += 10)
        {
            points.Add(new Point(i, random.Next(1, 300)));
        }

        // Now marshal back to the UI thread here...
        Dispatcher.Invoke(DispatcherPriority.Normal, 
            new Action( () => p.Points = points));

        // Optionally delay a bit here...
        Thread.Sleep(250);
    }
}