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-Class ?msg = 3655119#xx3655119xx,但这真的有必要吗?还是有一些更简单的解决方案?
我找到了一个使用 DispatcherTimer 和 Dispatcher.Run() 在新线程中启动消息泵的解决方案。为了停止调度程序并顺利退出服务,我使用了
if (_currentDispatcher != null) _currentDispatcher.InvokeShutdown();
_thread.Join();
Run Code Online (Sandbox Code Playgroud)