单击新按钮时,单击一个按钮事件

时间:2011-09-26 23:15:39

标签: wpf

单击新按钮时如何终止一个按钮的事件。

我有一个事件(按钮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();
        }
    }
}

3 个答案:

答案 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.CancellationPendingCancelAsync更改为true,导致while循环退出,从而执行以离开BackgroundWorkerTask事件处理程序。

简而言之,您可以在BackgroundWorkerTaskUpdateTime中的两个地方开展工作,但只能对UpdateTime的UI元素进行更改。

答案 1 :(得分:1)

不要在UI线程上执行旋转等待操作,例如使用新的ThreadTimer

答案 2 :(得分:1)

你做不到。 UI在单个线程中运行,通常称为main或ui线程。使用while循环,您将阻止整个ui线程,因此您无法接收任何进一步的输入。 我建议您查看BackgroundWorker课程,也可以查看更多关于如何设计线程和后台任务以便在ui环境中正常工作的MSDN文章。