Kill one button event when new button clicked
How to kill one button's event when a new button is clicked.
I have one event (Button G) running.(has a while loop waiting for some input). I have a another button for quit operation. Now. I cannot click any other button when button G's event is running. How can I solve that? Thanks
Hi, @Grokodile thank you for your code. So I commented your code here, Should I put my job logic code where I commented below? 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 = Dat开发者_如何转开发eTime.Now.ToString();
}
}
}
Futher to what H.B. and dowhilefor have said, here is a sample that shows starting a task on a background thread using BackgroundWorker with one Button and ending it with another Button, note the use of 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>
Code Behind
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();
}
}
}
EDIT - A Little More Explanation
RunButtonClickHandler
Creates and initializes a BackgroundWorker
so that it supports cancellation.
Attaches a DoWorkEventHandler
to the DoWork
event, i.e. BackgroundWorkerTask
.
Starts excecution of the background operation with the call to RunWorkerAsync
, i.e. creates a new thread (actually it uses a thread from the thread pool) and runs the code in BackgroundWorkerTask
on that thread.
BackgroundWorkerTask
If you want to do work that would otherwise cause the UI to freeze when running on the main UI thread (e.g. search for undiscovered prime numbers) then you do it here in the background thread.
UpdateTime
All WPF Control
s inherit from DispatcherObject
and are associated with a Dispatcher
which manages the execution of work done in the UI's single thread. If you need to do work such as setting the text of a TextBlock
, you can't do it from the background thread, trying to do so will cause an exception to be thrown. UpdateTime
is queued back onto the UI thread by the Dispatcher
when Dispatcher.BeginInvoke
is called from BackgroundWorkerTask
. This way you can get the results of work done in the background before cancelling the background threads execution.
StopButtonClickHandler
Changes _worker.CancellationPending
to true with the call to CancelAsync
causing the while loop to exit and thus for execution to leave the BackgroundWorkerTask
event handler.
In short, you can do work in two places, either in BackgroundWorkerTask
or in UpdateTime
, but you can only carry out changes to UI elements from UpdateTime
.
Don't do spin-waiting operations on the UI-thread, use a new Thread
or a Timer
for example.
You can't. The UI is running in a single thread, usually called the main or ui thread. With your while loop you are blocking the whole ui thread, thus you can't receive any further input. I suggest you check out BackgroundWorker class and maybe check some more MSDN articles about how the threading and background tasks should be designed to work properly in an ui enviroment.
精彩评论