C#SynchronizingObject和Timer.Timer线程

use*_*586 5 .net c# multithreading deadlock timer

嗨,我试图在我的主线程上触发Timer.Timer类的Elapsed事件。我仅限于VS 2008,.net 3.5 ...在本文中: C#计时器是否在单独的线程上运行了? 声明使用SynchronizingObject将使处理程序在拥有该对象的线程上执行。

所以我尝试了这个:

class MyTimer
{
  private readonly Timer timer;

  public MyTimer(ISynchronizeInvoke synchronizingObject)
  {
    Console.Out.WriteLine(Thread.CurrentThread.ManagedThreadId);
    timer = new Timer(1000);
    timer.SynchronizingObject = synchronizingObject;
    timer.Elapsed +=
      delegate
        {
          timer.Stop();
          Thread.Sleep(2000);
          Console.Out.WriteLine(Thread.CurrentThread.ManagedThreadId);
          timer.Start();

        };
    timer.Start();
  }
}

class Program
{
  static void Main(string[] args)
  {
    ISynchronizeInvoke syncObject = new Control();
    var mytimer = new MyTimer(syncObject);

    Console.ReadKey();
  }
}
Run Code Online (Sandbox Code Playgroud)

但是输出是:1,4,4,4,4 ...

这是为什么?如何使Elapsed处理程序在主线程上执行。

我尝试将SynchronizingObject用于事件, 但这也无济于事:

  public static ElapsedEventHandler Wrap(ElapsedEventHandler original, ISynchronizeInvoke synchronizingObject) 
  {
    return (sender, args) =>
    {
      if (synchronizingObject.InvokeRequired)
      {
        synchronizingObject.Invoke(original, new object[] { sender, args });
      }
      else
      {
        original(sender, args);
      }
    };
  }
Run Code Online (Sandbox Code Playgroud)

和:

timer.Elapsed += Wrap(
      delegate
        {
          timer.Stop();
          Thread.Sleep(200);
          Console.Out.WriteLine(Thread.CurrentThread.ManagedThreadId);
          timer.Start();
        }, 
        synchronizingObject);
Run Code Online (Sandbox Code Playgroud)

但是仍然没有成功...每次InvokeRequired为假...

强制将调试插入调用中将导致无效操作:“在创建窗口句柄之前,无法在控件上调用Invoke或BeginInvoke。”

不得已而为之:http//www.codeproject.com/Articles/12082/A-DelegateQueue-Classmsg = 3655119#xx3655119xx,但这真的有必要吗?还是有一些更简单的解决方案?

use*_*586 2

我找到了一个使用 DispatcherTimer 和 Dispatcher.Run() 在新线程中启动消息泵的解决方案。为了停止调度程序并顺利退出服务,我使用了

if (_currentDispatcher != null) _currentDispatcher.InvokeShutdown();
_thread.Join();
Run Code Online (Sandbox Code Playgroud)