我有一个在后台运行的异步函数。此功能通过TCP轮询数据。我有另一个函数GetClientNameById
,它将获取当前值并以json
格式返回。但是,我为所有值获得 NULL 。如何在中间中断,获取值并恢复轮询?以下是我的代码。
class Poll
{
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
public string D { get; set; }
public string E { get; set; }
}
public async void Polling(CancellationToken token)
{
await Task.Run(() =>
{
if (token.IsCancellationRequested)
{
return;
}
while (true)
{
if (token.IsCancellationRequested)
{
return;
}
//TODO
poll.A = reply1;
poll.B = reply2;
poll.C = reply3;
poll.D = reply4;
poll.E = DateTime.Now.ToString("HH:mm:ss.fff");
}
});
}
Poll poll = new Poll();
public string GetClientNameById(string Id)
{
string json = "";
if (Id == "Poll")
{
Console.WriteLine("Reply: " + poll.A + " " + poll.B + " " + poll.C + " " + poll.D + " " + poll.E);
json = JsonConvert.SerializeObject(poll, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.Indented });
}
return json;
}
答案 0 :(得分:0)
看起来您正在调用包含类的不同实例上的Polling
和GetClientNameById
函数。由于您的poll
变量被声明为此包含类的字段,因此每次都会创建一个新的实例。
确保在同一个实例上调用这些函数:
var myContainingClass = new MyContainingClass();
// Start polling
await myContainingClass.Polling(someCancellationToken);
// Call the GetClientNameById function on the same instance
// on which you called the Polling function
myContainingClass.GetClientNameById("Poll");
myContainingClass.GetClientNameById("Poll");
myContainingClass.GetClientNameById("Poll");
...
您的代码中也存在竞争条件。由于您在轮询功能中分配了4个字段,因此GetClientNameById
函数(如果同时调用)可能会查看从TCP调用的不同调用分配的那些字段。您可以考虑使用网关同步对此poll变量的访问:
private readonly ReaderWriterLockSlim gateway = new ReaderWriterLockSlim();
然后在写字段时获取写锁:
gateway.EnterWriteLock();
try
{
poll.A = reply1;
poll.B = reply2;
poll.C = reply3;
poll.D = reply4;
poll.E = DateTime.Now.ToString("HH:mm:ss.fff");
}
finally
{
gateway.ExitWriteLock();
}
阅读时:
if (Id == "Poll")
{
gateway.EnterReadLock();
try
{
Console.WriteLine("Reply: " + poll.A + " " + poll.B + " " + poll.C + " " + poll.D + " " + poll.E);
json = JsonConvert.SerializeObject(poll, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.Indented });
}
finally
{
gateway.ExitReadLock();
}
}
如果您不想对两个函数调用使用相同的实例,可以考虑将poll
字段设置为静态,以便在所有实例之间共享它。关于比赛条件的评论仍然适用,你需要正确地同步对这个领域的访问。