关于WPF的多线程问题

时间:2010-12-30 00:34:42

标签: .net wpf multithreading

我是线程新手,我真的不知道如何编写特定任务。我想在窗口上处理鼠标单击事件,该事件将在单独的线程中启动while循环。该线程与UI线程不同,应调用while循环中的函数,该函数更新UI线程所服务的窗口上的标签。当不再按下鼠标左键时,while循环应该停止运行。所有循环都是递增计数器,然后重复调用在窗口中显示更新值的函数。下面给出了窗口和所有线程的代码(我不断收到有关STA线程的错误,但不知道将属性放在何处)。此外,我希望使用这个解决方案,如果它可以工作,在另一个项目,通过wcf在服务的其他地方进行异步调用,所以我希望不要进行任何应用程序范围的特殊配置,因为我真的是新的多线程,并且非常担心在更大的程序中破坏其他代码......这就是我所拥有的:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication2"
        Name="MyMainWindow"
        Title="MainWindow" Width="200" Height="150"
        PreviewMouseLeftButtonDown="MyMainWindow_PreviewMouseLeftButtonDown">
    <Label Height="28" Name="CounterLbl" />
</Window>

这是代码隐藏的代码:

using System.Windows;
using System.Windows.Input;
using System.Threading;

namespace WpfApplication2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private int counter = 0;

        public MainWindow()
        {
            InitializeComponent();
        }

        private delegate void EmptyDelegate();

        private void MyMainWindow_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Thread counterThread = new Thread(new ThreadStart(MyThread));

            counterThread.Start();
        }

        private void MyThread()
        {
            while (Mouse.LeftButton == MouseButtonState.Pressed)
            {
                counter++;

                Dispatcher.Invoke(new EmptyDelegate(UpdateLabelContents), null);
            }
        }

        private void UpdateLabelContents()
        {
            CounterLbl.Content = counter.ToString();
        }
    }
}

无论如何,多线程对我来说真的很新,而且我没有任何实现它的经验,所以欢迎任何想法或建议!

谢谢,

安德鲁

修改

这是使用BackgroundWorker的另一个版本(我还添加了一个网格),它仍然抱怨调用线程必须是STA ...

<Window x:Class="WpfApplication2.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1"
        Name="MyMainWindow" Width="200" Height="150" PreviewMouseLeftButtonDown="MyMainWindow_PreviewMouseLeftButtonDown">
    <Grid>
        <Label Height="28" Name="CounterLbl" />
    </Grid>
</Window>

和背后的代码......

using System.Windows;
using System.Windows.Input;
using System.Threading;
using System.ComponentModel;

namespace WpfApplication2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        private int counter = 0;

        public Window1()
        {
            InitializeComponent();
        }

        private delegate void EmptyDelegate();

        private void MyMainWindow_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += new DoWorkEventHandler(MyThread);
            bw.RunWorkerAsync(this);
        }

        private void MyThread(object sender, DoWorkEventArgs e)
        {
            Window window = e.Argument as Window;

            while (Mouse.LeftButton == MouseButtonState.Pressed)
            {
                counter++;

                window.Dispatcher.Invoke(new EmptyDelegate(UpdateLabelContents), null);
            }
        }

        private void UpdateLabelContents()
        {
            CounterLbl.Content = counter.ToString();
        }
    }
}

1 个答案:

答案 0 :(得分:2)

为简单起见,请使用BackgroundWorker

这个答案:Is this thread/background worker design for a C# WPF application OK?有其他建议,但在你的情况下,BackgroundWorker似乎很合适,特别是因为ProgressChanged要求。