Я новичок в многопоточности, и я действительно не знаю, как кодировать конкретную задачу. Я хотел бы обработать событие щелчка мыши на окне, которое запустит цикл while в отдельном потоке. Этот поток, отличный от потока пользовательского интерфейса, должен вызывать функцию в цикле while, которая обновляет метку в окне, обслуживаемом потоком пользовательского интерфейса. Цикл 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();
}
}
}
В любом случае, многопоточность действительно нова для меня, и у меня нет никакого опыта в ее реализации, поэтому любые мысли и предложения приветствуются!
Спасибо
Andrew
Изменить:
Вот еще одна версия (я также добавил сетку) с использованием 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();
}
}
}