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

如何让ExternalEvent执行完成后再运行后续任务?

解决Revit ExternalEvent执行顺序问题

Revit的ExternalEvent.Raise()并非同步执行事件处理器,它只是将外部事件加入Revit的事件队列,当前UI线程会继续执行后续代码,因此Othertasks()会先于RunTestFunction()完成。以下是两种实现需求的方案:

方案一:将后续任务移至ExternalEvent处理器中

直接把需要延后执行的Othertasks()放到事件处理器的Execute方法内,在RunTestFunction()完成后调用,逻辑简单直接。

修改后的代码

首先调整事件处理器类,通过构造函数传入后续执行的方法:

public class ExternalEventhandle: IExternalEventHandler
{
    private readonly Action _postExecuteAction;

    // 构造函数接收后续要执行的任务
    public ExternalEventhandle(Action postAction)
    {
        _postExecuteAction = postAction;
    }

    public void Execute(UIApplication app)
    {
        UIDocument UIdoc = app.ActiveUIDocument;
        Document doc = UIdoc.Document;
        // 优先执行目标任务
        RunTestFunction();
        // 任务完成后执行后续操作
        _postExecuteAction?.Invoke();
    }

    public string GetName()
    {
        return "BtnClickedExternalEvent"; // 返回有意义的事件名称,避免空字符串
    }
}

然后初始化外部事件并修改按钮点击方法:

// 类成员变量,提前初始化外部事件
private ExternalEvent _btnClickedEvent;

// 在类构造函数或初始化方法中创建事件实例
public YourClassConstructor()
{
    _btnClickedEvent = ExternalEvent.Create(new ExternalEventhandle(Othertasks));
}

private void BtnClicked()
{
    _btnClickedEvent.Raise();
}

方案二:使用TaskCompletionSource异步等待(适合保留原方法结构)

如果Othertasks()需要访问按钮点击方法中的局部变量,或不想改动原方法结构,可以用TaskCompletionSource实现异步等待,避免阻塞UI线程。

修改后的代码

调整事件处理器类,添加TaskCompletionSource用于通知任务完成:

public class ExternalEventhandle: IExternalEventHandler
{
    public TaskCompletionSource<bool> CompletionSource { get; set; }

    public void Execute(UIApplication app)
    {
        try
        {
            UIDocument UIdoc = app.ActiveUIDocument;
            Document doc = UIdoc.Document;
            RunTestFunction();
            // 标记任务完成
            CompletionSource?.SetResult(true);
        }
        catch (Exception ex)
        {
            // 捕获异常并传递
            CompletionSource?.SetException(ex);
        }
    }

    public string GetName()
    {
        return "BtnClickedExternalEvent";
    }
}

将按钮点击方法改为异步方法,等待外部事件完成后再执行后续任务:

private async void BtnClicked()
{
    var tcs = new TaskCompletionSource<bool>();
    // 初始化事件处理器并绑定CompletionSource
    var eventHandler = new ExternalEventhandle { CompletionSource = tcs };
    var btnClickedEvent = ExternalEvent.Create(eventHandler);
    
    btnClickedEvent.Raise();
    // 异步等待外部事件执行完成
    await tcs.Task;
    // 执行后续任务
    Othertasks();
}

注意事项

  1. GetName()方法不要返回空字符串,提供有意义的名称有助于调试Revit事件。
  2. 方案一中建议提前初始化ExternalEvent实例,避免每次点击都重复创建,提升性能。
  3. 方案二中使用async void是因为UI事件处理方法的特殊性,若为普通方法建议返回Task。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 01:55:34