我有線程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. 在WxPython GUI線程上運行函數
- 6. 運行已經在OS X上運行的應用程序
- 7. 如何檢測一個進程是否已經完成執行
- 8. White如何在已經運行的應用程序上工作?
- 9. 如何啓動一個運行類函數的boost線程?
- 10. boost ::線程函數執行
- 11. 如何驗證一個進程是否已經在powershell上運行?
- 12. 英特爾TBB在並行線程中運行一個函數?
- 13. Java - 在現有的線程上運行一個可運行的?
- 14. 如何在Android中執行兩個線程時運行第三個線程
- 15. OpenMP將一個函數的執行分配給一個線程?
- 16. Cuda如何從全局函數運行多個線程?一個運行多線程的內核
- 17. 如果一個程序已經在運行,我該如何關閉程序?
- 18. 已排序執行線程
- 19. 如何在每個塊的線程數多於每個線程的線程上執行並行掃描?
- 20. 執行jQuery函數圖像已經裝上窗後調整
- 21. 線程池是否可以在單線程函數上運行?
- 22. 如何,你已經從一個可執行的VB
- 23. 如何判斷一個偵聽器是否已經在運行?
- 24. 在已經運行的c#過程中執行c#WPF應用程序
- 25. 運行兩個函數與線程
- 26. 如何確保函數a已經在函數b ..之前運行?
- 27. Java kill程序如果已經運行
- 28. Android如何在另一個線程上執行db插入?
- 29. 如何在codeigniter的每個頁面上運行一個函數
- 30. 在另一個線程中運行函數的C#泛型
某種類型的生產者 - 消費者模式,其中定時器推動價值和你直接調用推動它爲好,其中FunctionX()將其結果推送到另一個隊列? – CodeCaster
您是否熟悉Taskbased異步模式?你可以有一個專用線程等待一個阻塞隊列。您將TaskCompletionSource對象排入該隊列。在線程中,它將取消它,調用FunctionX並將CompletionSource結果設置爲函數的結果......只是一個想法。 – Fildor