1

所以我的问题是,当我为我的 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>

你们能告诉我这里有什么问题吗?

4

1 回答 1

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);
    }
}
于 2012-10-01T17:44:54.093 回答