You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# Battlefield 4插件如何等待响应事件完成后继续执行逻辑

解决方案

你可以通过TaskCompletionSource实现异步等待事件触发的逻辑,完全满足你不耦合事件和命令执行流程、无需修改事件原有签名的需求。TaskCompletionSource的作用就是把外部回调/事件触发的逻辑封装成可等待的Task,刚好匹配你的场景。

实现步骤

  1. 首先声明线程安全的字典存储待完成的命令对应等待源,避免多线程冲突
  2. 将原命令执行方法改为异步方法,每个命令发送前创建对应等待源,异步等待完成
  3. 在每个响应事件的末尾,匹配到对应等待源并标记为完成,即可唤醒后续命令执行

代码示例

首先添加类成员变量:

// 存储命令名对应等待源,线程安全
private readonly ConcurrentDictionary<string, TaskCompletionSource> _pendingCommandSources = new();

改造命令执行方法:

// 改为异步方法,上层调用时可直接await,不会阻塞插件主线程
private async Task PerformProconTasks(params string[] actions)
{
    foreach(var action in actions)
    {   
        var command = action.Split(' ');
        var commandName = command[0];
        
        // 为当前命令创建等待源,RunContinuationsAsynchronously避免同步阻塞事件线程
        var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
        _pendingCommandSources.TryAdd(commandName, completionSource);

        try
        {
            RegisterEvents(this.GetType().Name, InvocationDictionary[commandName]);
            ProconPluginEXT.ExecuteCommand(this, command);

            // 等待事件触发,增加超时逻辑避免服务器无响应时永久阻塞
            var timeoutTask = Task.Delay(TimeSpan.FromSeconds(30));
            var finishedTask = await Task.WhenAny(completionSource.Task, timeoutTask);

            if (finishedTask == timeoutTask)
            {
                // 自定义超时处理逻辑,比如输出错误日志
                this.ExecuteCommand("procon.protected.pluginconsole.write", $"^1Command {commandName} execution timed out");
            }
        }
        finally
        {
            // 执行结束清理等待源,避免内存泄漏
            _pendingCommandSources.TryRemove(commandName, out _);
        }
    }
}

修改事件处理逻辑,仅新增一行完成通知代码即可,无需修改原有事件逻辑:

public override void On3dSpotting(bool isEnabled)
{
    // 原有事件逻辑完全保留
    this.ExecuteCommand("procon.protected.pluginconsole.write", "^6Hello from the other side!");

    // 新增:匹配到对应命令的等待源,标记为完成,唤醒命令队列继续执行
    if (_pendingCommandSources.TryRemove("vars.3dSpotting", out var source))
    {
        source.SetResult();
    }
}

注意事项

  • 如果存在同一条命令并行发送的场景,可将字典key改为命令名+唯一请求ID的组合,避免匹配混乱
  • 禁止使用.Wait()/.Result等同步等待方式,会直接卡死插件主线程,必须全程使用async/await异步等待
  • 如果需要获取事件返回的参数,只需将TaskCompletionSource改为泛型版本,比如TaskCompletionSource<bool>,SetResult时传入事件参数,await时即可直接拿到返回值
  • 该方案完全解耦了事件和命令执行流程,命令流转逻辑全部在PerformProconTasks中维护,事件仅承担完成通知的作用,没有额外耦合

内容的提问来源于stack exchange,提问作者KodenameYT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 17:45:00