好吧,我已经搜索了很多解决方案.我正在寻找一种干净简单的方法来防止在我停止后调用System.Threading.Timer的回调方法.
我似乎无法找到任何东西,这导致我,在偶尔,诉诸可怕的线程 - thread.sleep-thread.abort组合颤抖.
可以用锁来完成吗?请帮我找到一个好办法.谢谢
在本文中:http://msdn.microsoft.com/en-us/magazine/cc164015.aspx作者声明System.Threading.Timer不是线程安全的.
从那时起,在Rich的书"CLR via C#"中,在博客上重复了这一点,但是这一点从来都不合理.
此外,MSDN文档确保"此类型是线程安全的".
1)谁说实话?
2)如果这是原始文章是什么使System.Threading.Timer不是线程安全的,它的包装器System.Timers.Timer如何实现更多线程安全?
谢谢
我正在开发一个UWP MVVM项目,并希望在用户交互停止一段特定时间时实现自动注销系统.
到现在为止,我DispatcherTimer每秒使用a 从200倒数.
TimerLeave = 200;
var _dispatcherTimer = new DispatcherTimer();
_dispatcherTimer.Tick += dispatcherTimer_Tick;
_dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
_dispatcherTimer.Start();
Run Code Online (Sandbox Code Playgroud)
但是因为DispatcherTimer与UI链接而我正在构建MVVM应用程序,所以我正在寻找替代方案.
我搜索了一下,发现在计时器上运行后台任务.问题是这个计时器只能设置为每15分钟运行一次,这在我的情况下自动注销用户有点太长了.我找不到减少15分钟的解决方法.
所以我的问题是,是否有可能在UWP项目中设置一个没有链接到UI并且可以设置变量的计时器?
我需要编写一个接收事件的组件(事件具有唯一的ID).每个活动都要求我发出请求.该事件指定一个超时期限,等待来自请求的响应.
如果响应在计时器触发之前响起,那很好,我取消了计时器.如果计时器首先触发,那么请求超时,我想继续前进.
此超时时间是在事件中指定的,因此它不是常量.预期的超时时间在30秒到5分钟的范围内.
我可以看到实现这个的两种方法.
选项1似乎是最简单的解决方案,但我担心创建这么多计时器可能不是一个好主意,因为计时器可能太昂贵了.在创建大量计时器时是否存在任何陷阱?我怀疑在后台,定时器实现可能实际上是选项2的有效实现.如果这个选项是个好主意,我应该使用哪个定时器?System.Timers.Timer或System.Threading.Timer.
选项2似乎更多的工作,与选项1相比可能不是一个有效的解决方案.
更新
我期望的最大定时器数量在10000的范围内,但更有可能在100的范围内.另外,正常情况是在发射之前取消定时器.
更新2
我使用10K实例运行测试,System.Threading.Timer并System.Timers.Timer密切关注线程数和内存.System.Threading.Timer与System.Timers.Timer通过内存使用判断相比,似乎"更轻" ,并且没有为两个定时器创建过多的线程(即 - 线程池正常工作).所以我决定继续使用System.Threading.Timer.
我用C#编写了一个控制台应用程序,我的代码是这样的:
while(true)
{
//do some stuff
System.Threading.Thread.Sleep(60000)
}
Run Code Online (Sandbox Code Playgroud)
我注意到我的应用程序的内存使用量大约是14k而"休眠".但后来我引用了System.Windows.Forms并使用了计时器,我发现内存使用率大幅下降.
我的问题是,在没有使用那么多内存的情况下,每隔几秒钟执行某项操作的正确方法是什么?
我正在制作一个控制台应用程序,必须在定时间隔内调用某个方法.
我已经搜索过了,发现System.Threading.Timer该类可以实现这样的功能,但我并没有完全遵循如何实现它.
我试过这个:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Timer x = new Timer(test, null, 0, 1000);
Console.ReadLine();
}
public static void test()
{
Console.WriteLine("test");
}
}
}
Run Code Online (Sandbox Code Playgroud)
但我Timer x = new Timer(test, null, 0, 1000);在行上写了一个错误:
对于System.Threading.Timer.Timer(System.Threading.TimerCallback,对象,INT,INT)"最好重载的方法匹配具有一些无效参数
我真的不知道如何使这项工作正常,但如果有人有链接或某些东西可以解释初学者的计时器,我将不胜感激.
使用System.Threading.Timer从a中旋转的线程的结果ThreadPool,这意味着如果计时器的执行间隔在线程仍在按先前请求的顺序处理时到期,则将委托相同的回调在另一个线程上执行.在大多数情况下,这显然会导致问题,除非回调是可重入的,但我想知道如何以最好的(意味着安全的)方式去做.
假设我们有以下内容:
ReaderWriterLockSlim OneAtATimeLocker = new ReaderWriterLockSlim();
OneAtATimeCallback = new TimerCallback(OnOneAtATimeTimerElapsed);
OneAtATimeTimer = new Timer(OneAtATimeCallback , null, 0, 1000);
Run Code Online (Sandbox Code Playgroud)
整个shebang应该被锁定,如下:
private void OnOneAtATimeTimerElapsed(object state)
{
if (OneAtATimeLocker.TryEnterWriteLock(0))
{
//get real busy for two seconds or more
OneAtATimeLocker.ExitWriteLock();
}
}
Run Code Online (Sandbox Code Playgroud)
或者,应该只管理输入,并踢出'侵入者',如下:
private void OnOneAtATimeTimerElapsed(object state)
{
if (!RestrictOneAtATime())
{
return;
}
//get real busy for two seconds or more
if(!ReleaseOneAtATime())
{
//Well, Hell's bells and buckets of blood!
}
}
bool OneAtATimeInProgress = false;
private …Run Code Online (Sandbox Code Playgroud) 我使用一个System.Threading.Timer对象,并设置它的周期:
// period of 1 second
var timer = new Timer(CallBack, null, 0, 1000);
...
Run Code Online (Sandbox Code Playgroud)
现在我想获取我的计时器的时间,我该怎么做?
使用Device.StartTimervs的优点或缺点是System.Threading.Timer什么?
两者都在后台线程上触发,两者都是跨平台和 netstandard2 兼容的。System.Threading.Timer具有非 Xamarin 特定的奖励积分。
我应该使用什么以及何时使用?
System.Threading.Timer似乎所有计时器都使用专用线程。我是对的,还是 Xamarin 使用其他实现?有谁知道这段代码是否是线程安全的,或者在调用timer2.Change时是否必须使用锁?
Timer timer1 = new Timer(timerCallback1);
Timer timer2 = new Timer(timerCallback2);
timer1.Change(5000, 5000);
timer2.Change(3000, 3000);
public void timerCallback1(object state)
{
timer1.Change(Timeout.Infinite, Timeout.Infinite);
timer2.Change(Timeout.Infinite, Timeout.Infinite);
DoStuff();
timer1.Change(5000, 5000);
timer2.Change(3000, 3000);
}
Run Code Online (Sandbox Code Playgroud) 我编写了一个类,该方法在线程池中作为长时间运行的Task运行.该方法是一种监视服务,用于定期发出REST请求以检查另一个系统的状态.它只是一个while()循环,里面有一个try()catch(),这样它就可以处理自己的异常,并在发生意外情况时正常继续.
这是一个例子:
public void LaunchMonitorThread()
{
Task.Run(() =>
{
while (true)
{
try
{
//Check system status
Thread.Sleep(5000);
}
catch (Exception e)
{
Console.WriteLine("An error occurred. Resuming on next loop...");
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
它工作正常,但我想知道是否有另一种模式我可以使用它将允许Monitor方法作为标准Async/Await应用程序的常规部分运行,而不是使用Task.Run()启动它 - 基本上我'我试图避免火灾和遗忘模式.
所以我尝试重构代码:
public async Task LaunchMonitorThread()
{
while (true)
{
try
{
//Check system status
//Use task.delay instead of thread.sleep:
await Task.Delay(5000);
}
catch (Exception e)
{
Console.WriteLine("An error occurred. Resuming on next loop...");
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是当我尝试在另一个异步方法中调用该方法时,我得到了有趣的编译器警告:
"因为没有等待这个调用,所以在调用完成之前,当前方法的执行仍在继续."
现在我认为这是正确的,我想要的.但我怀疑是因为我是async/await的新手.这段代码是按照我预期的方式运行还是以DEADLOCK或其他致命的方式运行?