Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 关于WPF的多线程问题_.net_Wpf_Multithreading - Fatal编程技术网

.net 关于WPF的多线程问题

.net 关于WPF的多线程问题,.net,wpf,multithreading,.net,Wpf,Multithreading,我是线程新手,我真的不知道如何编写特定任务的代码。我想处理一个窗口上的鼠标点击事件,它将在一个单独的线程中启动while循环。此线程与UI线程不同,它应该调用while循环中的一个函数,该函数更新由UI线程提供服务的窗口上的标签。当不再按下鼠标左键时,while循环应停止运行。循环所做的只是增加一个计数器,然后重复调用在窗口中显示更新值的函数。下面给出了窗口和所有线程的代码(我一直得到一些关于STA线程的错误,但不知道该属性放在哪里)。此外,我希望在另一个项目中使用此解决方案(如果可行的话),该

我是线程新手,我真的不知道如何编写特定任务的代码。我想处理一个窗口上的鼠标点击事件,它将在一个单独的线程中启动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();
        }
    }
}
使用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上。。。