[英]c# asynchronously call method
這個類unit
具有屬性bool status
,用於標記是否應在單元上調用方法, request
。 我有我的另一個類,在其中,有一個方法應該調用request
。 為了避免阻塞主線程,我想異步調用該方法。 問題是沒有狀態更改的事件,我不想讓我的異步調用做丑陋的事情,如:
while(!status){}unit.request(args);
要么
while(!status){Thread.Sleep(100)}unit.request(args);
特別是當我不知道status
變為true
時間尺度時。
我該怎么做呢?
更新:我忘了提到我不能改變unit
。 對不起
您希望在屬性更改時調用函數(無論是否異步)。 你有兩個選擇:
你不能做第一個,所以你必須做第二個。
以下是使用事件管理此方法的示例。
假設這是你的班級
public class Unit
{
private readonly object _syncRoot = new object();
private bool _status;
public event EventHandler OnChanged;
public bool Status
{
get
{
lock (_syncRoot)
{
return _status;
}
}
set
{
lock (_syncRoot)
{
_status = value;
if (_status && OnChanged != null)
{
OnChanged.Invoke(this, null);
}
}
}
}
public void Process()
{
Thread.Sleep(1000);
Status = true;
}
}
以下是如何使用它
class Program
{
static void Main(string[] args)
{
var unit = new Unit();
unit.OnChanged += Unit_OnChanged;
Console.WriteLine("Before");
Task.Factory.StartNew(unit.Process);
Console.WriteLine("After");
Console.WriteLine("Manual blocking, or else app dies");
Console.ReadLine();
}
static void Unit_OnChanged(object sender, EventArgs e)
{
//Do your processing here
Console.WriteLine("Unit_OnChanged before");
Task.Factory.StartNew(()=>
{
Thread.Sleep(1000);
Console.WriteLine("Unit_OnChanged finished");
});
Console.WriteLine("Unit_OnChanged after");
}
}
這輸出
Before After Manual blocking, or else app dies Unit_OnChanged before Unit_OnChanged after Unit_OnChanged finished
這是典型的輪詢問題,在輪詢時確實沒有一個優雅的解決方案。 但是我們可以使用一些函數式編程來獲得一些不是噩夢的東西。
public static CancellationTokenSource Poll(
Func<bool> termination,
Action<CancellationToken> onexit,
int waitTime = 0,
int pollInterval = 1000)
{
var cts = new CancellationTokenSource();
var token = cts.Token;
Action dispose = cts.Cancel;
var timer = new Timer(_ =>
{
if (termination() || token.IsCancellationRequested)
{
onexit(token);
dispose();
}
}, null, waitTime, pollInterval);
dispose = timer.Dispose;
return cts;
}
例:
var condition = false;
Poll(() => condition == true, ct => Console.WriteLine("Done!"));
Console.ReadLine();
condition = true;
Console.ReadLine();
如果可能,請使用System.Threading.AutoResetEvent
而不是bool
:
AutoResetEvent status = new AutoResetEvent();
在異步方法中,等待它:
status.WaitOne();
unit.request(args);
然后,要在您的其他課程中發出信號,請致電Set
:
status.Set();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.