【问题标题】:timer inside thread线程内的计时器
【发布时间】:2011-07-08 08:42:32
【问题描述】:

我的目标:我有一个信用卡等待窗口。我将从客户端调用一个函数来等待信用卡刷卡。为了避免程序在等待信用卡时卡住。我正在使用委托来运行计时器。代表将调用一个计时器。计时器定期检查卡的存在。如果它找到一张卡片,它将由客户端分配一个回调/委托。

代码如下,我的问题是 1) _timer_Elapsed 是否会在线程内被调用,从而为 ui 窗口增加最小的开销?

2) 我如何从定时器函数调用基类的回调/事件。我编写了一个受保护的方法,它将在基类中调用事件/委托。我需要从定时器函数(在派生类的委托中)调用受保护的方法?

Wait wait = delegate()
{

    _timer = new Timer(3000); // Set up the timer for 3 seconds

    _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
    _timer.Enabled = true; // Enable it
    static void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        // if(CheckCardsPresence())
        {
            //RaiseEvent()
            //KillTimer()
        }
        //else
        {
            // do nothing. wait more
        }

    }

};

wait.Invoke();

【问题讨论】:

    标签: c# .net multithreading timer


    【解决方案1】:

    不,计时器回调将不会在委托线程上执行。

    1. 怎么可能?计时器不能“闯入”线程,该线程必须轮询。
    2. 此委托线程将在启动计时器后立即终止。这意味着你根本不需要这个线程。除非没有显示代码。

    当您使用 System.Threading.Timer 时,回调将被推送到线程池。

    第二个问题(尽量一次只问一个问题)

    • 应该可以通过匿名(嵌入式)方法访问受保护的成员。您有具体问题吗?

    【讨论】:

      【解决方案2】:

      来自MSDN documentation(抱歉我第一次上错课了)

      此 Windows 计时器专为使用 UI 线程执行处理的单线程环境而设计。它要求用户代码具有可用的 UI 消息泵。

      这是一种迂回的说法,即事件将在 UI 线程/消息泵上引发,即只要“线程”是指“UI 线程”,您的第一个问题的答案是肯定的。

      我不太明白你的第二个问题 - 你在说什么基类?

      【讨论】:

      • 我认为问题中的 Timer 是 WinForms Timer。
      • 委托是从具有基类的类中调用的。基类有一个可以由客户的消费者分配的事件。
      • @Henk 其实我们都错了——它来自System.Timers
      • @logeeks:您的描述没有多大帮助。在问题中添加 C# 大纲。
      【解决方案3】:

      首先,该代码无法编译。您不能从另一个方法中声明命名方法。但是,您可以声明一个匿名方法或 lambda 表达式,然后将其分配给委托引用。

      可能不需要对信用卡设备进行异步轮询。您也许可以使用System.Windows.Forms.Timer 并从在 UI 线程上运行的Tick 事件执行轮询。如果CheckCardsPresence 是一个快速操作,这是可以接受的。

      public class CreditCardWaitWindow : Form
      {
        private System.Windows.Timer timer = new System.Windows.Timer();
      
        private void Form_Load(object sender, EventArgs args)
        {
          timer.Tick += OnTick;
          timer.Interval = 3000;
          timer.Start();
        }
      
        private void OnTick(object sender, EventArgs args)
        {
          if (CheckCardsPresence())
          {
            RaiseEvent();
            timer.Stop();
          }
        }
      }
      

      如果轮询信用卡设备是一项耗时的操作,那么您需要在另一个线程上执行此操作以避免阻塞 UI。

      public class CreditCardWaitWindow : Form
      {
        private System.Timers.Timer timer = new System.Timers.Timer();
      
        private void Form_Load(object sender, EventArgs args)
        {
          timer.Elapsed += OnElapsed;
          timer.Interval = 3000;
          timer.AutoReset = false;
          timer.Start();
        }
      
        private void OnElapsed(object sender, ElapsedEventArgs args)
        {
          if (CheckCardsPresence())
          {
            Invoke(
              (MethodInvoker)(() =>
              {
                RaiseEvent();
              }), null);
          }
          else
          {
            timer.Start();
          }
        }
      }
      

      这是一个使用Task 的更简洁的实现。

      public class CreditCardWaitWindow : Form
      {
        private void Form_Load(object sender, EventArgs args)
        {
          Task.Factory.StartNew(
            () =>
            {
              while (true)
              {
                Thread.Sleep(3000);
                if (CheckCardsPresence()) break;
              }
            }, TaskCreationOptions.LongRunning).ContinueWith(
            () =>
            {
              RaiseEvent();
            }, TaskScheduler.FromCurrentSychronizationContext());
        }    
      }
      

      最重要的是,您可以在 C# 5.01 中使用新的 await 关键字来执行此操作。我不确定它是否能比这更简洁!

      public class CreditCardWaitWindow : Form
      {
        private async void Form_Load(object sender, EventArgs args)
        {
          while (!CheckCardsPresence()) await Task.Delay(3000);
          RaiseEvent();
        }
      }
      

      1C# 5.0 尚未发布。

      【讨论】:

        猜你喜欢
        • 2012-06-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-30
        • 2017-03-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多