我有一个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();
}
}
计时器似乎可以正常工作,但它仍然会以块的形式发送更新 - 这是否意味着它不在自己的线程上?
答案 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
中的顺序代码必须经常检查暂停事件信号状态,在子任务,内部循环或顺序工作方法中的任何内容之间。