在继续执行代码之前,如何等待回调方法响应之一?

时间:2020-06-17 01:25:46

标签: c# callback steamworks-api

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

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 ***");
}

从上面的代码片段可以看到,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();
}

1 个答案:

答案 0 :(得分:0)

我假设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的所有访问,以免出现竞争状况。