.net 关于WPF的多线程问题
我是线程新手,我真的不知道如何编写特定任务的代码。我想处理一个窗口上的鼠标点击事件,它将在一个单独的线程中启动while循环。此线程与UI线程不同,它应该调用while循环中的一个函数,该函数更新由UI线程提供服务的窗口上的标签。当不再按下鼠标左键时,while循环应停止运行。循环所做的只是增加一个计数器,然后重复调用在窗口中显示更新值的函数。下面给出了窗口和所有线程的代码(我一直得到一些关于STA线程的错误,但不知道该属性放在哪里)。此外,我希望在另一个项目中使用此解决方案(如果可行的话),该项目通过wcf在其他地方对服务进行异步调用,因此我不希望进行任何应用程序范围的特殊配置,因为我对多线程非常陌生,并且非常担心在更大的程序中破坏其他代码。。。以下是我所拥有的:.net 关于WPF的多线程问题,.net,wpf,multithreading,.net,Wpf,Multithreading,我是线程新手,我真的不知道如何编写特定任务的代码。我想处理一个窗口上的鼠标点击事件,它将在一个单独的线程中启动while循环。此线程与UI线程不同,它应该调用while循环中的一个函数,该函数更新由UI线程提供服务的窗口上的标签。当不再按下鼠标左键时,while循环应停止运行。循环所做的只是增加一个计数器,然后重复调用在窗口中显示更新值的函数。下面给出了窗口和所有线程的代码(我一直得到一些关于STA线程的错误,但不知道该属性放在哪里)。此外,我希望在另一个项目中使用此解决方案(如果可行的话),该
<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();
}
}
}
使用System.Windows;
使用System.Windows.Input;
使用系统线程;
命名空间WpfApplication2
{
///
///MainWindow.xaml的交互逻辑
///
公共部分类主窗口:窗口
{
专用整数计数器=0;
公共主窗口()
{
初始化组件();
}
私有委托void EmptyDelegate();
私有void MyMain窗口\u预览鼠标左键向下(对象发送器,鼠标按钮ventargs e)
{
线程反向线程=新线程(新线程开始(MyThread));
counterThread.Start();
}
私有void MyThread()
{
while(Mouse.LeftButton==MouseButtonState.Pressed)
{
计数器++;
Invoke(新的EmptyDelegate(UpdateLabelContents),null);
}
}
私有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();
}
}
}
使用System.Windows;
使用System.Windows.Input;
使用系统线程;
使用系统组件模型;
命名空间WpfApplication2
{
///
///MainWindow.xaml的交互逻辑
///
公共部分类Window1:Window
{
专用整数计数器=0;
公共窗口1()
{
初始化组件();
}
私有委托void EmptyDelegate();
私有void MyMain窗口\u预览鼠标左键向下(对象发送器,鼠标按钮ventargs e)
{
BackgroundWorker bw=新的BackgroundWorker();
bw.DoWork+=新DoWorkEventHandler(MyThread);
RunWorkerAsync(this);
}
私有void MyThread(对象发送方,DoWorkEventArgs e)
{
Window Window=e.参数为Window;
while(Mouse.LeftButton==MouseButtonState.Pressed)
{
计数器++;
Invoke(新的EmptyDelegate(UpdateLabelContents),null);
}
}
私有void UpdateLabelContents()
{
CounterLbl.Content=counter.ToString();
}
}
}
为简单起见,请使用
- 乔·阿尔巴哈里的
这个问题的答案是:有其他建议,尽管在你的情况下,后台工作人员似乎很适合,特别是因为ProgressChanged的要求。@Mitch:谢谢Mitch!我正在研究你的建议——它们看起来很有前途。我将尝试修改代码以使用BackgroundWorker,这似乎是可行的。我一试用就会发回@米奇:好吧,我试过使用BackgroundWorker,但我似乎遇到了与STAThread相同的问题。我不确定这方面的最佳解决方案是什么。我将把BackgroundWorker版本以“编辑”的方式发布到原始问题…@Andrew:你是否连接了ProgressChanged事件处理程序,并且只使用它和完成的处理程序来更新UI?@Mitch:嗯。。。实际上,我试图将对窗口的引用作为参数传递给worker方法。通过这种方式,我认为可以从worker方法调用一个方法来通过窗口的调度程序更新UI。。。(然后在循环中一次又一次地执行此操作,因为worker方法仍将运行…)ProgressChanged和Completed事件处理程序,为您将其添加到UI上。。。