等待任务x的时间,并报告进度。

时间:2021-08-03 02:20:32

I need a better design for sleeping Task than Thread.Sleep, I'm using the Task class.

我需要一个比线程更好的睡眠任务设计。睡觉,我在用任务类。

In my wpf app i run a Task, this task runs another couple of tasks, each of this tasks first login to and Internet website, after they login they need to wait couple of seconds and inform the user when they will proceed further and this is my problem, because with Thread.Sleep i can't report the progress.

我在wpf应用程序运行一个任务,这个任务运行另一个任务,这个任务和互联网网站第一次登录,登录后他们需要等待几秒钟,通知用户时将进一步进行,这是我的问题,因为线程。睡觉,我不能报告进展。

There are more functions than login, it's about 5-6, all of them request an Internet resource, and between them there need to be a sleep time with remaining time report send do gui, this 5-6 function are all in one Task, but there could be many tasks.

有比登录更多的功能,大约5-6个,它们都请求一个Internet资源,在它们之间需要有一个睡眠时间,剩余的时间报告发送do gui,这个5-6函数都在一个任务中,但是可能有很多任务。

What i need is to make the task wait, but also allow it to send updates on the remaining time to proceed to the GUI.

我需要的是让任务等待,但也允许它在剩余时间发送更新以继续到GUI。

Do you have any ideas for this problem, how to make it better, maybe you have some design patterns already for such problem?

你对这个问题有什么想法吗,如何做的更好,也许你已经有一些设计模式来解决这个问题了?

I have heard also that using Thread.Sleep is a poor design practice.

我也听说过用线。睡眠是一种糟糕的设计实践。

EDIT: No one knows ? Whats with some kind of self contained timer with thread wait like waithandle, autoresetevent, anybody?

编辑:没人知道?什么是有自我约束的计时器和线程等,像waithandle, autoresetevent,有人知道吗?

4 个解决方案

#1


1  

Forget using Thread.Sleep. Instead, run your task in a background thread and use a WaitHandle with an AutoResetEvent. (Links: WaitHandle/WaitOne / AutoReset)

忘记使用thread . sleep。相反,在后台线程中运行任务,并使用带有AutoResetEvent的WaitHandle。(链接:WaitHandle / WaitOne / AutoReset)

Your background thread can send updates to UI with async delegates, but the calling thread will wait it until either thing happens:

您的后台线程可以使用异步委托向UI发送更新,但调用线程将等待它,直到发生以下两种情况:

1) Your thread reports it has completed its task by using yourwaithandle.Set();

你的线程报告它已经通过使用你的waithandle.set()完成了它的任务;

or

2) the waiting thread timeouts (timeout value is set as parameter to WaitOne() -method).

2)等待线程超时(超时值设置为WaitOne()方法的参数)。

#2


6  

The solution is to treat it as async callback, rather than a synchronous wait. If you are on the Async CTP, the right way would be to:

解决方案是将其视为异步回调,而不是同步等待。如果您使用的是异步CTP,正确的方法应该是:

async item => { await Task.Delay(1000); Process(item); }

异步项=>{等待任务。延迟(1000);过程(项目);}

This also seems like an ideal use case for DataFlow or Rx.

这似乎也是DataFlow或Rx的理想用例。

Using Reactive Extensions:

使用活性扩展:

static void Track(int timeout, int frequency, string item)
    {
        Observable.Interval(TimeSpan.FromSeconds(frequency)) //produces 0, 1, 2.. with the interval
                  .Do(i => Console.WriteLine("Working on {0}", item)) // work on item
                  .TakeUntil(Observable.Timer(TimeSpan.FromSeconds(timeout))) //stop once the timer publishes a value
                  .Subscribe
                  (
                        i => Console.WriteLine("Reporting {0}%", ((double)(i + 1) / timeout * 100)), // the interval reaches OnNext
                        e => Console.WriteLine("Error!"), // error occured 
                        () => Console.WriteLine("Completed") // observable completed
                  );
    }

On calling this with Track(timeout: 5, frequency: 1, item: "http://example.com/?"), the output produced is:

通过跟踪(超时:5,频率:1,项目:“http://example.com/?”),输出的是:

Working on http://example.com/?
Reporting 20%
Working on http://example.com/?
Reporting 40%
Working on http://example.com/?
Reporting 60%
Working on http://example.com/?
Reporting 80%
Completed

#3


1  

Rather than having a single task perform all of those half-dozen functions (login, etc.), make each function a separate task. You can then create a priority queue, ordered by time. When you want to start one of these meta-tasks, you place its first function into a queue along with the state data (i.e. url, user id, password, etc.).

与其让一个任务执行所有这些半打函数(登录等),不如将每个函数单独作为一个任务。然后可以创建一个按时间排序的优先队列。当您想要启动其中一个元任务时,您将它的第一个函数连同状态数据(例如url、用户id、密码等)一起放置到队列中。

As each function is completed, it queues the next function to be performed. So if the first two functions are login and get_data, you'd have:

当每个函数完成时,它会对要执行的下一个函数进行排队。因此,如果前两个函数是login和get_data,那么您将有:

queue login with state data to execute at DateTime.Now
When login is finished, it queues get_data with the state data and DateTime.Now + 5 seconds (or whatever time)

When the last function executes, it posts the results somewhere.

当最后一个函数执行时,它会在某个地方发布结果。

You can then set up a timer that will poll the queue 10 times per second (or have the timer's next tick time be updated whenever something is added to the queue). It can start individual tasks as required.

然后,您可以设置一个计时器,该计时器将每秒轮询队列10次(或者在向队列添加内容时更新计时器的下一次计时)。它可以根据需要启动单个任务。

The new Async CTP might have this kind of thing already: a "execute task at time". Might be worth looking into it.

新的异步CTP可能已经有了这样的东西:“执行任务时刻”。也许值得研究一下。

As for reporting progress, each function can report progress when it starts (i.e. "logging in" ... "waiting 5 seconds to get data" ... "getting data," etc.) If you want, you can make the timer thread walk the priority queue periodically and report when particular tasks will be executed. Although that might be overkill.

至于报告进度,每个函数都可以在开始时报告进度(例如。“登录”…“等待5秒获取数据”……“获取数据”等)如果您愿意,可以让计时器线程定期遍历优先级队列,并在执行特定任务时报告。尽管这可能有点过头了。

And what you heard is right: Thread.Sleep is an exceptionally bad idea, especially when you're working with thread pool threads.

你所听到的是正确的:线程。睡眠是一个非常糟糕的想法,尤其是在使用线程池线程时。

#4


0  

Have you considered using a Timer (from System.Timers) to perform the interstitial "time remaining" message updates? Each of your tasks could set an expected time to completion value, then your timer task could be responsible for counting down and updating the UI as necessary. No Thread.Sleep required, and Timer will execute its Tick code on a thread pool thread.

您是否考虑过使用计时器(来自system .Timer)来执行间隙的“剩余时间”消息更新?您的每个任务都可以将预期的时间设置为完成值,然后您的计时器任务可以负责计数并根据需要更新UI。没有线程。睡眠是必需的,计时器将在线程池线程上执行它的滴答代码。

#1


1  

Forget using Thread.Sleep. Instead, run your task in a background thread and use a WaitHandle with an AutoResetEvent. (Links: WaitHandle/WaitOne / AutoReset)

忘记使用thread . sleep。相反,在后台线程中运行任务,并使用带有AutoResetEvent的WaitHandle。(链接:WaitHandle / WaitOne / AutoReset)

Your background thread can send updates to UI with async delegates, but the calling thread will wait it until either thing happens:

您的后台线程可以使用异步委托向UI发送更新,但调用线程将等待它,直到发生以下两种情况:

1) Your thread reports it has completed its task by using yourwaithandle.Set();

你的线程报告它已经通过使用你的waithandle.set()完成了它的任务;

or

2) the waiting thread timeouts (timeout value is set as parameter to WaitOne() -method).

2)等待线程超时(超时值设置为WaitOne()方法的参数)。

#2


6  

The solution is to treat it as async callback, rather than a synchronous wait. If you are on the Async CTP, the right way would be to:

解决方案是将其视为异步回调,而不是同步等待。如果您使用的是异步CTP,正确的方法应该是:

async item => { await Task.Delay(1000); Process(item); }

异步项=>{等待任务。延迟(1000);过程(项目);}

This also seems like an ideal use case for DataFlow or Rx.

这似乎也是DataFlow或Rx的理想用例。

Using Reactive Extensions:

使用活性扩展:

static void Track(int timeout, int frequency, string item)
    {
        Observable.Interval(TimeSpan.FromSeconds(frequency)) //produces 0, 1, 2.. with the interval
                  .Do(i => Console.WriteLine("Working on {0}", item)) // work on item
                  .TakeUntil(Observable.Timer(TimeSpan.FromSeconds(timeout))) //stop once the timer publishes a value
                  .Subscribe
                  (
                        i => Console.WriteLine("Reporting {0}%", ((double)(i + 1) / timeout * 100)), // the interval reaches OnNext
                        e => Console.WriteLine("Error!"), // error occured 
                        () => Console.WriteLine("Completed") // observable completed
                  );
    }

On calling this with Track(timeout: 5, frequency: 1, item: "http://example.com/?"), the output produced is:

通过跟踪(超时:5,频率:1,项目:“http://example.com/?”),输出的是:

Working on http://example.com/?
Reporting 20%
Working on http://example.com/?
Reporting 40%
Working on http://example.com/?
Reporting 60%
Working on http://example.com/?
Reporting 80%
Completed

#3


1  

Rather than having a single task perform all of those half-dozen functions (login, etc.), make each function a separate task. You can then create a priority queue, ordered by time. When you want to start one of these meta-tasks, you place its first function into a queue along with the state data (i.e. url, user id, password, etc.).

与其让一个任务执行所有这些半打函数(登录等),不如将每个函数单独作为一个任务。然后可以创建一个按时间排序的优先队列。当您想要启动其中一个元任务时,您将它的第一个函数连同状态数据(例如url、用户id、密码等)一起放置到队列中。

As each function is completed, it queues the next function to be performed. So if the first two functions are login and get_data, you'd have:

当每个函数完成时,它会对要执行的下一个函数进行排队。因此,如果前两个函数是login和get_data,那么您将有:

queue login with state data to execute at DateTime.Now
When login is finished, it queues get_data with the state data and DateTime.Now + 5 seconds (or whatever time)

When the last function executes, it posts the results somewhere.

当最后一个函数执行时,它会在某个地方发布结果。

You can then set up a timer that will poll the queue 10 times per second (or have the timer's next tick time be updated whenever something is added to the queue). It can start individual tasks as required.

然后,您可以设置一个计时器,该计时器将每秒轮询队列10次(或者在向队列添加内容时更新计时器的下一次计时)。它可以根据需要启动单个任务。

The new Async CTP might have this kind of thing already: a "execute task at time". Might be worth looking into it.

新的异步CTP可能已经有了这样的东西:“执行任务时刻”。也许值得研究一下。

As for reporting progress, each function can report progress when it starts (i.e. "logging in" ... "waiting 5 seconds to get data" ... "getting data," etc.) If you want, you can make the timer thread walk the priority queue periodically and report when particular tasks will be executed. Although that might be overkill.

至于报告进度,每个函数都可以在开始时报告进度(例如。“登录”…“等待5秒获取数据”……“获取数据”等)如果您愿意,可以让计时器线程定期遍历优先级队列,并在执行特定任务时报告。尽管这可能有点过头了。

And what you heard is right: Thread.Sleep is an exceptionally bad idea, especially when you're working with thread pool threads.

你所听到的是正确的:线程。睡眠是一个非常糟糕的想法,尤其是在使用线程池线程时。

#4


0  

Have you considered using a Timer (from System.Timers) to perform the interstitial "time remaining" message updates? Each of your tasks could set an expected time to completion value, then your timer task could be responsible for counting down and updating the UI as necessary. No Thread.Sleep required, and Timer will execute its Tick code on a thread pool thread.

您是否考虑过使用计时器(来自system .Timer)来执行间隙的“剩余时间”消息更新?您的每个任务都可以将预期的时间设置为完成值,然后您的计时器任务可以负责计数并根据需要更新UI。没有线程。睡眠是必需的,计时器将在线程池线程上执行它的滴答代码。