与中断异步

时间:2017-01-23 09:51:34

标签: c# web-services asynchronous

我有一个在后台运行的异步函数。此功能通过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;
}

1 个答案:

答案 0 :(得分:0)

看起来您正在调用包含类的不同实例上的PollingGetClientNameById函数。由于您的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字段设置为静态,以便在所有实例之间共享它。关于比赛条件的评论仍然适用,你需要正确地同步对这个领域的访问。