2011-09-26 89 views
1

如何在单击新按钮时杀死一个按钮的事件。单击新按钮时杀死一个按钮事件

我有一个事件(按钮G)正在运行(有一个while循环等待一些输入)。 我有另一个退出操作按钮。 现在。 G按钮的事件正在运行时,我无法点击任何其他按钮。 我该如何解决这个问题? 谢谢

嗨,@Grokodile谢谢你的代码。所以我在这里评论你的代码,我应该把我的工作逻辑代码放在我下面评论的地方吗? 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

不,您应该将自己的'作业逻辑'放在BackgroundWorkerTask或UpdateTime中,只需使用XXXButtonClickHandler方法来启动和停止执行,请参阅我的编辑 – Grokodile

回答

3

进一步向H.B.和dowhilefor说,这里是显示了启动使用BackgroundWorker的一个按钮,并用另一个按钮结束它在后台线程任务的样本,请注意使用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继承,并与管理工作在UI的单一线程中完成执行一个Dispatcher相关。如果您需要执行诸如设置TextBlock的文本之类的工作,则无法从后台线程执行此操作,尝试这样做会导致抛出异常。当从BackgroundWorkerTask调用Dispatcher.BeginInvoke时,UpdateTime排队回到UI线程的Dispatcher。通过这种方式,您可以在取消后台线程执行前获得后台完成的工作结果。

StopButtonClickHandler

变化_worker.CancellationPending与呼叫真实CancelAsync导致while循环执行离开BackgroundWorkerTask事件处理程序退出,因此。

总之,您可以在两个地方工作,不管是在BackgroundWorkerTask还是在UpdateTime,但只能对UpdateTime的UI元素进行更改。

+0

感谢您的代码。请帮我看看我在我的问题帖子中评论过的代码。这是放置我的工作逻辑代码的正确位置吗?谢谢 –

+0

@Anders,我试着在编辑中多解释一下,希望有所帮助。 – Grokodile

1

不要做UI线程自旋等待的操作,使用新Thread或例如Timer

1

你不能。 UI在单线程中运行,通常称为主线程或ui线程。用你的while循环你会阻塞整个UI线程,因此你不能接收任何进一步的输入。 我建议你查看BackgroundWorker类,也许可以查看更多有关如何设计线程和后台任务以在UI环境中正常工作的MSDN文章。