【问题标题】:How to wait for a one of callbacks method response before continuing the code?如何在继续代码之前等待一个回调方法响应?
【发布时间】:2020-06-17 01:25:46
【问题描述】:

我目前正在开发一个主动跟踪服务器信息的系统。对于一些方法,我需要它是异步的,但是,有一些是以同步方式实现的(外部库)。我有这个代码:

m_ServerQuery = HServerQuery.Invalid;

m_PingResponse = new ISteamMatchmakingPingResponse(OnServerResponded, OnServerFailedToRespond);
try
{
    m_ServerQuery = SteamMatchmakingServers.PingServer((uint)ip, port, m_PingResponse);
    await Task.Delay(500);
    SteamMatchmakingServers.CancelServerQuery(m_ServerQuery);
}
    catch
{
    Console.WriteLine($"*** Something went wrong while pinging server ***");
}

从上面的代码 sn-p 中可以看出,PingResponse 类继承了两个方法,当从 Steam 发送响应时,它们作为“回调”工作。现在等待它 0.5 毫秒是可行的,但是,我认为最好实现它以等待这两种方法之一触发: OnServerResponded, OnServerFailedToRespond 我怎么能做到这一点? ISteamMatchmakingPingResponse 定义:

public class ISteamMatchmakingPingResponse
{
    public ISteamMatchmakingPingResponse(ServerResponded onServerResponded, ServerFailedToRespond onServerFailedToRespond);

    ~ISteamMatchmakingPingResponse();

    public static explicit operator IntPtr(ISteamMatchmakingPingResponse that);

    public delegate void ServerResponded(gameserveritem_t server);
    public delegate void ServerFailedToRespond();
}

【问题讨论】:

  • 你可以同步等待AutoResetEvent,或者如果你想让这个返回任务与async和await一起使用,使用TaskCompletionSource

标签: c# callback steamworks-api


【解决方案1】:

我假设OnServerRespondedOnServerFailedToRespond 是您可以修改的函数。您可以使用 TaskCompletionSource<bool> 并等待它的任务。像这样的。

TaskCompletionSource<bool> pingSucceed;

//Not sure about the firm of your callback functions, just a void function for this example
void OnServerResponded()
{
    //Do any task you need to do
    //..

    if(pingSucceed != null)
        pingSucceed.TrySetResult(true);
}

void OnServerFailedToRespond()
{
    //Do any task you need to do
    //..

    if(pingSucceed != null)
        pingSucceed.TrySetResult(false);
}

//Now the call
async Task TheFunctionThatPingsTheServer()
{
    //Do any task you need to do prior to the ping
    //..

    pingSucceed = new TaskCompletionSource<bool>();
    m_ServerQuery = SteamMatchmakingServers.PingServer((uint)ip, port, m_PingResponse);
    var succeed = await pingSucceed.Task;
    pingSucceed.Dispose();
    pingSucceed = null;

    //Here succeed will be true if server answered, else false.

}

注意这一点,如果OnServerResponded 和/或OnServerFailedToRespond 在不同的线程中运行,那么您必须通过锁定对象来保护对pingSucceed 的所有访问以避免竞争条件。

【讨论】:

  • 我会尝试修改它,看看效果如何,稍后会给出更新
猜你喜欢
  • 2014-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-22
  • 2016-06-02
  • 2019-04-23
  • 1970-01-01
相关资源
最近更新 更多