1

我正在编写一个程序,该程序有几个“工人”对象启动并执行需要设定时间的任务。我创建了一个带有工作正常的内部计时器的工人类。然而,在做“工作”时,我有时需要等待几秒钟来刷新屏幕(每个工作人员都在从远程屏幕上抓取数据并进行一些自动化操作)。

对于那些暂停,我不想让线程休眠,因为据我了解,这也会暂停其他工作对象上的计时器(我的应用程序是单线程,因为坦率地说,我是 C# 的新手,而且我不想超越)。是否有另一个我可以使用的等待功能实际上不会挂起整个线程?

一些附加信息:

  • 现在这是一个控制台应用程序,但我最终将构建一个 UI 表单,向用户提供有关工人工作情况的反馈
  • 我的计时器是使用 System.Timers 实现的,并且工作得很好
  • 我是 C# 编程的新手,这是我的第一个项目,所以请用小词;)
  • 使用 MS VS Express 2012 for Desktop(所以无论是什么版本的 C#/.NET!)

下面的代码(实际工作将使用“startWorking”方法完成,但没有实现任何东西 - 这只是我出售的带有计时器的构建。此外,主要现在只是用于测试多个计时器)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace Multi_Timers
{
//worker class that includes a timer
public class Worker
{
    private Timer taskTimer;
    private bool available = true;
    private string workerName;
    private string startWork;
    private int workTime;

    // properties
    public bool isAvailable { get { return this.available; } }
    public string name { get { return this.workerName; } }

    // constructor
    public Worker(string name)
    {
        this.workerName = name;
        Console.WriteLine("{0} is initialized", name);
    }

    // start work timer
    public void startWorking(int duration) {

        if (this.available == true)
        {
            this.available = false;
            this.taskTimer = new Timer();
            this.taskTimer.Interval = duration;
            this.taskTimer.Elapsed += new ElapsedEventHandler(doneWorking);
            this.taskTimer.Enabled = true;
            this.startWork = DateTime.Now.ToString();
            this.workTime = duration / 1000;
        }
        else Console.WriteLine("Sorry, {0} was not available to work", this.workerName);
    }

    // Handler for timer
    public void doneWorking(object sender, ElapsedEventArgs e)
    {
        Console.WriteLine("{0}: {1} / {2} min / {3}", this.workerName, this.startWork, this.workTime/60, e.SignalTime.ToLocalTime());
        this.taskTimer.Enabled = false;

        this.available = true;

    }
}

//main program
class Program
{
    static void Main(string[] args)
    {
        Random r = new Random();

        // initialize worker(s)
        Worker bob = new Worker("Bob");
        Worker bill = new Worker("Bill");
        Worker jim = new Worker("Jim");

        // q to exit
        while (true)
        {
            if (bob.isAvailable) {

                bob.startWorking(r.Next(1 * 60, 150 * 60) * 1000);
            }
            if (bill.isAvailable)
            {
                bill.startWorking(r.Next(1 * 60, 150 * 60) * 1000);
            }
            if (jim.isAvailable)
            {
                jim.startWorking(r.Next(1 * 60, 150 * 60) * 1000);
            }

        }
    }
}
}

感谢您提前提供任何帮助!阅读这个社区的示例绝对是自学一点 C# 入门的关键!

4

2 回答 2

3

我不想让线程休眠,因为据我所知,这也会暂停其他工作对象上的计时器

这是不正确的;它不会停止计时器。

我的应用程序是单线程

不,实际上,它不是。计时器将创建和使用其他线程来实现它们的行为。事件Elapsed处理程序将从线程池线程中触发。


您的代码的一个主要问题是您的main方法正在对三个对象执行“busywait”,不断轮询它们询问它们是否完成。这……贵。这基本上就像你是孩子在问,“我们到了吗?” 每秒几百次。如果他们只是坐等你告诉他们你已经完成了,那不是更好吗!(这是很有可能的,也是一个不错的选择。)

在这种情况下,更简单的解决方案之一是在工作程序中执行循环,而不是Main. 将实现startWorking包装在一个while循环中,并让 main 永远等待(即Thread.Sleep(Timeout.Infinite);)。更复杂的选择是让工作人员提供一个Task、事件或阻塞等待(也称为“加入”)方法来指示他们何时完成。

您正在考虑的选项,即添加Thread.Sleep一点时间Main有所帮助,但这只是告诉您的孩子在您较少的时候问您,而不是让他们等您告诉他们您什么时候那里。

于 2013-01-23T15:42:06.183 回答
-1

如果您发现自己想在不同的上下文中再次延迟执行,您可以考虑这样的实现:

private static void DelayExecution(Action action, TimeSpan delay)
{
    TimeSpan start = DateTime.Now.TimeOfDay;
    Thread t = new Thread(() =>
    {
        while (DateTime.Now.TimeOfDay < start.Add(delay))
        {
            //Block
        }
        action.Invoke();
    });
    t.Start();
}

private static void Main(string[] args)
{
    DelayExecution(() => Console.WriteLine("Delayed Execution"), TimeSpan.FromSeconds(1));
    Console.ReadLine();
}
于 2013-01-23T16:07:15.880 回答