是否可以包装特定的类或方法并将它们分配给一个线程?

时间:2011-02-11 00:39:07

标签: c# .net multithreading methods

我有一个XAML表单,我想要从主XAML执行线程中穿出两个独立的功能:1。)一个滴答的计时器控件,以及2.)实现一个暂停按钮,这样我就可以冻结一组程序一系列活动并再次点击暂停按钮将恢复。

当我启动表单时,整个应用程序冻结。因此,我无法与btnPause控件进行交互。我让计时器类工作,但它(lblTimer)以块的形式更新,或者当它看起来CPU在主线程上不忙时。

我尝试创建一个类“Task”,它在自己的线程中包装一个类或方法,以便我可以控制。

    Automation.Task AutomationThread = new Automation.Task();
    Automation.Task TimerThread = new Automation.Task();

后来,我尝试创建一个秒表类并为其分配TimerThread,以便我可以独立管理它。

    Automation.WatchTimer stopwatch = new Automation.WatchTimer(lblTimer, TimerThread);


class Task
{
    private ManualResetEvent _shutdownFlag = new ManualResetEvent(false);
    private ManualResetEvent _pauseFlag = new ManualResetEvent(true);

    Thread _thread;

    public Task() { }

    public void Start()
    {
        _thread = new Thread(DoWork);
        _thread.Start();
    }

    public void Resume()
    {
        _pauseFlag.Set();
    }

    public void Stop()
    {
        _shutdownFlag.Set();
        _pauseFlag.Set();
        _thread.Join();
    }

    public void DoWork()
    {
        do
        {
            _pauseFlag.WaitOne(Timeout.Infinite);
        }
        while (!_shutdownFlag.WaitOne(0));
    }

    // I AM NOT SURE IF THIS IS THE RIGHT APPROACH
    public void DoWork(Func<void> method????)
    {
        do
        {
            // NOT SURE WHAT TO PUT HERE
            // This is where I want it to do a method 
            // that wraps a long chain of procedural items
            // where I can pause (block) and unpause through the UI
        }
        while (!_shutdownFlag.WaitOne(0));
    }

class WatchTimer
{
    public WatchTimer(System.Windows.Controls.Label lbl, Automation.Task worker)
    {
        lblField = lbl;
        worker.Start();
    }

    private System.Windows.Controls.Label lblField;

    Timer time = new Timer();
    Stopwatch sw = new Stopwatch();

    public void Start()
    {
        time.Start();
        sw.Start();
        time.Tick += new EventHandler(time_Tick);
    }

    public void Stop()
    {
        time.Stop();
        sw.Stop();
    }

    public void Reset()
    {
        sw.Reset();
        lblField.Content = this.elapsedTime();
    }

    public string elapsedTime()
    {
        TimeSpan ts = sw.Elapsed;
        // return formatted TimeSpan value
        return String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
            ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
    }

    private void time_Tick(object sender, EventArgs e)
    {
        lblField.Content = this.elapsedTime();
    }

}

计时器似乎可以正常工作,但它仍然会以块的形式发送更新 - 这是否意味着它不在自己的线程上?

2 个答案:

答案 0 :(得分:1)

您很可能会崩溃,因为当您不在UI线程上时,您正在更新Windows控件。完成标签控件更新的最简单方法是使用System.Windows.Forms.Timer而不是System.Threading.Timer。上述SWF Timer可以设置为每隔x毫秒触发一次,并且保证事件处理程序在UI线程上运行!

答案 1 :(得分:0)

由于一个CPU与100%挂钩,导致明显挂起。这是因为_pauseFlag的初始状态设置为发信号。因此,当主线程调用new Thread(DoWork)时,DoWork会不断超越_pauseFlag.WaitOne并在紧密的do/while循环中运行。

要在一个线程中包含一些方法,暂停,这可能是可行的。您必须从do/while方法中删除DoWork。因此,DoWork中的顺序代码必须经常检查暂停事件信号状态,在子任务,内部循环或顺序工作方法中的任何内容之间。