此类unit
有一个属性bool status
,用于标记是否应在单元上调用方法request
。我有我的另一个类,其中有一个方法应该调用request
。为了避免阻塞主线程,我想异步调用该方法。问题是没有状态更改的事件,我不想让我的异步调用做丑陋的事情,如:
while(!status){}unit.request(args);
或
while(!status){Thread.Sleep(100)}unit.request(args);
尤其是当我不知道status
转为true
的时间刻度时。
我该怎么做?
更新:我忘了提到我无法更改unit
。对不起。
答案 0 :(得分:2)
您希望在属性更改时调用函数(无论是否异步)。你有两个选择:
你不能做第一个,所以你必须做第二个。
答案 1 :(得分:2)
以下是使用事件管理此内容的示例。
假设这是你的班级
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
答案 2 :(得分:1)
这是典型的轮询问题,在轮询时确实没有一个优雅的解决方案。但是我们可以使用一些函数式编程来获得一些不是噩梦的东西。
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();
答案 3 :(得分:0)
如果可能,请使用System.Threading.AutoResetEvent
代替bool
:
AutoResetEvent status = new AutoResetEvent();
在异步方法中,等待它:
status.WaitOne();
unit.request(args);
然后,要在其他课程中发出信号,请致电Set
:
status.Set();