Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 检查取消时让后台工作人员睡觉_C#_Wpf_Multithreading_Backgroundworker - Fatal编程技术网

C# 检查取消时让后台工作人员睡觉

C# 检查取消时让后台工作人员睡觉,c#,wpf,multithreading,backgroundworker,C#,Wpf,Multithreading,Backgroundworker,我有一个后台工作人员,通过ReportProgress定期更新GUI 更新以固定的间隔进行,例如每5秒更新一次,也可以是20秒。为了在设定的时间执行更新,我将工作进程发送到休眠状态,并在其唤醒时使用新信息更新GUI worker支持取消,并且在睡眠之外,它可以正确地取消 我希望能够在等待期间调用取消,但是将线程发送到睡眠状态会使这变得不可能 我假设我必须调用一个循环,并在循环中检查取消,以模拟线程睡眠 实现这一目标的最佳方法是什么?我的尝试完全没有把握时机 long co

我有一个后台工作人员,通过ReportProgress定期更新GUI

更新以固定的间隔进行,例如每5秒更新一次,也可以是20秒。为了在设定的时间执行更新,我将工作进程发送到休眠状态,并在其唤醒时使用新信息更新GUI

worker支持取消,并且在睡眠之外,它可以正确地取消

我希望能够在等待期间调用取消,但是将线程发送到睡眠状态会使这变得不可能

我假设我必须调用一个循环,并在循环中检查取消,以模拟线程睡眠

实现这一目标的最佳方法是什么?我的尝试完全没有把握时机

            long counter = 0;
            long sleepfor = timelinespeed*1000;
            int timelinespeed = 10;

                while (counter != sleepfor)
                {

                    Thread.Sleep(1);

                    counter++;

                    if (bkgwk.CancellationPending)
                    {
                        cancelled = true;
                        e.Cancel = true;
                        bkgwk.Dispose();
                        break;
                    }

                }

你走错了路

  • Bgw正在使用线程池,因此应用于(相对)较短的操作,通常不超过0.5秒。不建议无限期地保留一个
  • 您几乎不应该在任何线程上使用
    Sleep()
    。当然不会超过几分钟
  • 在繁忙的等待中使用
    Sleep(1)
    5秒钟是对CPU的巨大浪费。你正在伤害你的其他线程。最起码考虑把它升级到<代码>睡眠(100)< /代码>左右。找到您允许取消的最大延迟
解决方法:使用计时器。如果你有一项定期任务,请使用正确的工具

使用
System.Threading.Timer
进行基于线程池的后台工作。通过Dispatcher.Invoke()更新GUI

使用
Dispatcher.Timer
在主线程上执行小部分(小于0.1秒)的工作。您可以直接更新GUI。

您可以使用允许线程在不轮询的情况下等待,也可以允许另一个线程随时唤醒它

ManualResetEvent
以及任何其他线程同步对象都有一个
WaitOne
方法,可以等待事件设置或超时。因此,通常您可以让
WaitOne
等待您想要等待的数量(这将像
Thread.Sleep
)但主线程可以随时唤醒后台线程

ManualResetEvent backgroundWakeEvent = new ManualResetEvent(false);
....
bkgwk.CancelAync();
backgroundWaitEvent.Set();
....
backgroundWakeEvent.WaitOne(5000);

if (bkgwk.CancellationPending)
{
    cancelled = true;
    e.Cancel = true;
    bkgwk.Dispose();
    break;
}
或者更好的方法是,使用并让“工作人员”观察一系列间隔事件。然后可以很容易地处理流以停止生成新事件,从而终止工作进程。将此功能与一次性取消功能相结合,您可以使用一个一次性取消功能来停止间隔计时器和任何正在执行其工作的工作人员:

var cancel = new BooleanDisposable();
var subscription = Observable.Interval(TimeSpan.FromSeconds(20))
                             .ObserveOn(Scheduler.DispatcherScheduler)
                             .Subscribe(i => PerformWorkOnUI(cancel));
var uiWork = new CompositeDisposable(cancel, subscription);
要取消计时器事件流,您只需处理复合取消/订阅:

uiWork.Dispose();

澄清:
ObserveOn(Scheduler.DispatchersScheduler)
确保将在调度程序线程上调用订阅。

+1获取计时器建议。如果您正在使用wpf,还可以查看调度程序计时器。取消变得很容易——只要停止计时器(假设允许任何当前任务完成是可以的),System.Threading.timer是否允许我用信息更新GUI?MSDN建议使用System.Windows.Forms.Timer,但这是单线程的?Forms.Timer和Dispatcher.Timer都在主线程上运行,因此我不会将它们用于繁重的操作。从其他线程更新GUI是相同的:使用Dispatcher.Invoke()