我有线程A每5秒钟用一个定时器调用FunctionX()。但是有时我需要立即从另一个线程(线程B)获得FunctionX()的值,并且不能等待定时器执行。我无法直接从线程B调用FunctionX(),因为它使用了一些外部组件,如果从另一个线程调用而不是原始内容,那么这些组件会死掉。所以FunctionX()必须总是在线程A上运行。如何在线程B上立即获取FunctionX()的值,而无需等待定时器调用该函数?如何在已经运行的线程上执行一个函数?
3
A
回答
1
这将取决于您使用定时器的类型,但System.Threading.Timer
类,作为一个例子,暴露了一个Change
方法,你可以用它来说服计时器现在火。下面是一个控制台应用程序测试工具的例子:
using System;
using System.Threading;
namespace FiringTheTimerTestHarness
{
class Program
{
public static Thread _worker;
public static Timer _timer;
static void Main(string[] args)
{
_worker = new Thread(new ThreadStart(ThreadWorker));
_worker.Start();
var startTime = DateTime.Now;
// Simulate the main UI thread being active doing stuff (i.e. if there's a Windows Forms app so we don't need anything to
// keep the app "alive"
while (1==1)
{
Thread.Sleep(100);
if (startTime.AddSeconds(30) < DateTime.Now)
{
// Lets pretend that we need to fire the timer *now* so that we can get the result *now*
_timer.Change(0, 5000);
}
}
}
public static void ThreadWorker()
{
_timer = new Timer(new TimerCallback(DoStuffEveryFiveSeconds), null, 5000, 5000);
while (1 == 1)
{
Thread.Sleep(100);
}
}
public static void DoStuffEveryFiveSeconds(object state)
{
Console.WriteLine("{0}: Doing stuff", DateTime.Now);
}
}
}
你会看到的输出看起来是这样的:
2017年5月9日10时04分44秒:做的东西
2017年5月9日10时04分49秒:做的东西
2017年5月9日10时04分54秒:做的东西
2017年5月9日10时04分59秒:做的东西
2017年5月9日10时05分04秒:做的东西
2017年5月9日10时05分09秒:做的东西
2017年5月9日10时05分09秒:做东西
2017年5月9日10时05分09秒:做的东西
2017年5月9日10时05分09秒:做的东西
2017年5月9日10时05分09秒:做东西
因此,计时器每5秒钟触发一次(如预期的),然后每隔100毫秒开始触发一次。 “一经请求”)。这个代码坐在一个人为的测试工具,所以看起来有点奇怪,但其目的基本上是向您展示调用Change
方法的结果。
0
这是概要我在谈论的评论。 完全未经测试 !!
class FunctionXCaller
{
private Task mTask;
private BlockingCollection<TaskCompletionSource<TResult>> queue = new BlockingCollection<TaskCompletionSource<TResult>>();
public FunctionXCaller()
{
mTask = Task.Run(() => WorkerMethod);
}
private void WorkerMethod()
{
while(!queue.IsCompleted)
{
TaskCompletionSource<TResult> tcs = queue.take();
tcs.TrySetResult(FunctionX());
}
}
public Task<TResult> CallXAsync()
{
TaskCompletionSource<TResult> tcs = new TaskCompletionSource<TResult>();
queue.Add(tcs);
return tcs.Task;
}
}
注意:正如我已经写道,这只是为了让你一个想法。有很多需要添加,如关闭,清理,异常处理,...
这个想法是你可以从任何线程调用await FunctionXCallerInstance.CallXAsnc()
并让FunctionX永远在工作线程上执行。这将是一个ThreadPool线程。
0
下面介绍如何轻松地与微软的反应框架(Rx)的做到这一点:
void Main()
{
EventLoopScheduler threadA = new EventLoopScheduler();
IObservable<int> timer = Observable.Interval(TimeSpan.FromSeconds(5.0), threadA).Select(x => FunctionX());
IDisposable subscription = timer.Subscribe(x => Console.WriteLine("timer: " + x));
Thread.Sleep(TimeSpan.FromSeconds(12.5));
int value = Observable.Start(() => FunctionX(), threadA).Wait();
Console.WriteLine("value: " + value);
}
private int counter = 0;
public int FunctionX()
{
Console.Write("ManagedThreadId: " + Thread.CurrentThread.ManagedThreadId + "; ");
Console.Write(DateTime.Now.ToString("ss.ffff") + "; ");
return ++counter;
}
的这个测试代码的输出是这样的:
ManagedThreadId: 13; 47.5655; timer: 1 ManagedThreadId: 13; 52.5601; timer: 2 ManagedThreadId: 13; 55.0649; value: 3 ManagedThreadId: 13; 57.5592; timer: 4 ManagedThreadId: 13; 02.5594; timer: 5 ManagedThreadId: 13; 07.5741; timer: 6
注意第三个值获得2.5秒之间的值和之间的值,并且这是标记“值”的唯一值。其他人有“计时器”。
如果您有什么需要运行在threadA
只是这样做:
threadA.Schedule(() => { /* Do this on `threadA` */ });
相关问题
- 1. 在另一个已经打开的窗体上执行函数
- 2. 如何在另一个线程中运行一个函数
- 3. 如何运行另一个线程后一个线程已经完成了它的行动
- 4. 线程已经停止运行
- 5. 只允许两个线程在一个函数上运行
- 6. 在QWidgets线程的实例上运行一个lambda函数槽
- 7. 在WxPython GUI线程上运行函数
- 8. 运行已经在OS X上运行的应用程序
- 9. 如何把一个已经运行的子进程下的nohup
- 10. 如何在gdb中执行函数后执行一个函数?
- 11. 确定一个线程已经运行了多长时间
- 12. 我如何“漂亮”一个已经运行的过程?
- 13. 如何检测一个进程是否已经完成执行
- 14. 如何运行一个线程在python外线程中调用的函数
- 15. White如何在已经运行的应用程序上工作?
- 16. 运行线程的run()方法的线程已经完成
- 17. 如何启动一个运行类函数的boost线程?
- 18. 如何使用线程运行一个简单的函数
- 19. 如何防止cron作业执行,如果它已经运行
- 20. boost ::线程函数执行
- 21. 如何验证一个进程是否已经在powershell上运行?
- 22. 如何并行执行一个函数?
- 23. 你如何获得一个进程已经运行了多久?
- 24. 如何运行(执行后)在一个线程自动释放一个信号?
- 25. 英特尔TBB在并行线程中运行一个函数?
- 26. 在有限数目的多个线程上运行函数
- 27. 如何在已经给课程上运行延迟加载?
- 28. 如何在Android中执行两个线程时运行第三个线程
- 29. Java - 在现有的线程上运行一个可运行的?
- 30. 在一个CPU上运行Java线程
某种类型的生产者 - 消费者模式,其中定时器推动价值和你直接调用推动它为好,其中FunctionX()将其结果推送到另一个队列? – CodeCaster
您是否熟悉Taskbased异步模式?你可以有一个专用线程等待一个阻塞队列。您将TaskCompletionSource对象排入该队列。在线程中,它将取消它,调用FunctionX并将CompletionSource结果设置为函数的结果......只是一个想法。 – Fildor