单击新按钮时如何终止一个按钮的事件。
我有一个事件(按钮G)正在运行。(有一个while循环等待一些输入)。 我有一个退出操作的另一个按钮。 现在。当按钮G的事件运行时,我无法单击任何其他按钮。 我怎么解决这个问题? 感谢
嗨,@ Grakodile感谢您的代码。所以我在这里评论了你的代码,我应该将我的工作逻辑代码放在下面评论的位置吗? Thans
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private BackgroundWorker _worker;
public MainWindow()
{
InitializeComponent();
}
private void RunButtonClickHandler(object sender, RoutedEventArgs e)
{
_worker = new BackgroundWorker {WorkerSupportsCancellation = true};
_worker.DoWork += BackgroundWorkerTask;
_worker.RunWorkerAsync();
//I should Put my job logic here, right?
}
private void StopButtonClickHandler(object sender, RoutedEventArgs e)
{
if (_worker != null && _worker.IsBusy) _worker.CancelAsync();
//I should Put my job logic here, right?
}
private void BackgroundWorkerTask(object sender, DoWorkEventArgs e)
{
// this runs on the BackgroundWorker thread.
while (_worker.CancellationPending == false)
{
Thread.Sleep(500);
// You have to use the Dispatcher to transfer the effects of
// work done in the worker thread back onto the UI thread.
Dispatcher.BeginInvoke(new Action(UpdateTime), DispatcherPriority.Normal, null);
}
}
private void UpdateTime()
{
// Dispatcher runs this on the UI thread.
timeTextBlock.Text = DateTime.Now.ToString();
}
}
}
答案 0 :(得分:3)
继续H.B.和dowhilefor说,这是一个示例,显示在后台线程上使用带有一个Button的BackgroundWorker开始一个任务,并用另一个Button结束它,注意使用Dispatcher.BeginInvoke:
<强> XAML 强>
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="80"
Width="640"
FontSize="16">
<DockPanel VerticalAlignment="Center">
<Button Margin="10,0"
x:Name="runButton"
DockPanel.Dock="Left"
Click="RunButtonClickHandler">Run</Button>
<Button Margin="10,0"
x:Name="stopButton"
DockPanel.Dock="Left"
Click="StopButtonClickHandler">Stop</Button>
<TextBlock Margin="10,0">The Time Is Now:</TextBlock>
<TextBlock x:Name="timeTextBlock"
Margin="10,0" />
</DockPanel>
</Window>
代码背后
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private BackgroundWorker _worker;
public MainWindow()
{
InitializeComponent();
}
private void RunButtonClickHandler(object sender, RoutedEventArgs e)
{
_worker = new BackgroundWorker {WorkerSupportsCancellation = true};
_worker.DoWork += BackgroundWorkerTask;
_worker.RunWorkerAsync();
}
private void StopButtonClickHandler(object sender, RoutedEventArgs e)
{
if (_worker != null && _worker.IsBusy) _worker.CancelAsync();
}
private void BackgroundWorkerTask(object sender, DoWorkEventArgs e)
{
// this runs on the BackgroundWorker thread.
while (_worker.CancellationPending == false)
{
Thread.Sleep(500);
// You have to use the Dispatcher to transfer the effects of
// work done in the worker thread back onto the UI thread.
Dispatcher.BeginInvoke(new Action(UpdateTime), DispatcherPriority.Normal, null);
}
}
private void UpdateTime()
{
// Dispatcher runs this on the UI thread.
timeTextBlock.Text = DateTime.Now.ToString();
}
}
}
编辑 - 更多解释
RunButtonClickHandler
创建并初始化BackgroundWorker
,以便它支持取消
将DoWorkEventHandler
附加到DoWork
事件,即BackgroundWorkerTask
通过调用RunWorkerAsync
开始执行后台操作,即创建一个新线程(实际上它使用线程池中的线程)并在该线程上运行BackgroundWorkerTask
中的代码。
BackgroundWorkerTask
如果你想做的工作会导致UI在主UI线程上运行时冻结(例如搜索未发现的素数),那么你可以在后台线程中这样做。
注册
所有WPF Control
都继承自DispatcherObject
,并与Dispatcher
相关联,后者负责管理UI单线程中完成的工作的执行。如果您需要执行诸如设置TextBlock
的文本之类的工作,则无法从后台线程执行此操作,尝试这样做会导致抛出异常。从UpdateTime
调用Dispatcher
时,Dispatcher.BeginInvoke
会将BackgroundWorkerTask
排队回UI线程。这样,您可以在取消后台线程执行之前获得后台完成的工作结果。
StopButtonClickHandler
通过调用_worker.CancellationPending
将CancelAsync
更改为true,导致while循环退出,从而执行以离开BackgroundWorkerTask
事件处理程序。
简而言之,您可以在BackgroundWorkerTask
或UpdateTime
中的两个地方开展工作,但只能对UpdateTime
的UI元素进行更改。
答案 1 :(得分:1)
不要在UI线程上执行旋转等待操作,例如使用新的Thread
或Timer
。
答案 2 :(得分:1)
你做不到。 UI在单个线程中运行,通常称为main或ui线程。使用while循环,您将阻止整个ui线程,因此您无法接收任何进一步的输入。 我建议您查看BackgroundWorker课程,也可以查看更多关于如何设计线程和后台任务以便在ui环境中正常工作的MSDN文章。