Building Coder(Revit 二次开发) - 失败处理API(下)

本文深入探讨了Revit二次开发中错误处理机制,包括标准失败解决UI、失败处理周期及其三个关键步骤(失败预处理、失败处理事件、最终处理),并通过示例展示了如何自定义失败解决方案及警告处理方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Building Coder 链接:Failure API Take Two

Revit 二次开发论坛链接:翻译 Building Coder - 失败处理API(下)


错误处理
正常情况下,被报告的失败会在事务提交时由 Revit 标准的失败解决 UI 来处理。用户会看到相关信息和可能的处理选项。当然,如果对文档的操作要求对一些特定(或者所有)错误做特殊处理的话,程序员就需要自定义失败解决方案了。

Revit 会在所有事务的提交阶段检测是否存在失败。一旦发现,Revit 会进入一个重复的失败解决周期。每个周期又包含三个步骤:
1. 失败预处理(IFailurePreprocessor)
2. 失败处理事件(FailureProcessing Event)
3. 最终处理(IFailureProcessor)

在一个周期中这三个步骤被依次执行。每个步骤都能控制本步骤的行为和是否进入下一个步骤(通过返回不同的 FailureProcessingResults 值)。已知事务时,可以使用 IFailuresPreprocessor。如果需要处理所有可能的错误,则应使用 FailureProcessing Event。终极解决方案是 IFailureProcessor,它能完全取代 Revit 的标准失败处理。

实现 IFailuresPreprocessor 接口和它的 PreprocessFailures() 方法来处理失败。注册事件并且定义处理器来处理失败。实现 IFailureProcessor 接口和它的 ProcessFailures() 方法来实现最终的失败处理。

每一步我们都可以删除元素,删除警告信息,解决或者报告一个失败。所有的动作都可以被封装在 FailuresAccessor 类中。

处理警告
下面让我们来看一个警告处理的例子。在试图删除被链接模型的最后一个实例时,如果没有实现建立失败处理机制,Revit 会报告如下警告信息:


用户可以手动单击三个按钮来选择处理方式。如果利用失败处理 API,我们就可以模拟用户的手动操作了。首先我们使用一个事件来处理这个警告。你可以如下面代码所示的
那样定义事件处理器,并在一个外部命令中注册 FailuresProcessing 事件:

public class RegisterFailureEvent : IExternalCommand
{
  public Result Execute(
    ExternalCommandData commandData,
    ref string messages,
    ElementSet elements )
  {
    UIApplication app = commandData.Application;
    Document doc = app.ActiveUIDocument.Document;
 
    app.Application.FailuresProcessing += new EventHandler<FailuresProcessingEventArgs>( OnFailuresProcessing );
 
    return Result.Succeeded;
  }
 
  /// <summary>
  /// 事件处理器
  /// </summary>
  private void OnFailuresProcessing(
    object sender,
    FailuresProcessingEventArgs e )
  {
    FailuresAccessor failuresAccessor = e.GetFailuresAccessor();
 
    String transactionName = failuresAccessor.GetTransactionName();
 
    IList<FailureMessageAccessor> fmas = failuresAccessor.GetFailureMessages();
 
    if( fmas.Count == 0 )
    {
      // 允许失败处理周期进入下一个步骤
      e.SetProcessingResult( FailureProcessingResult.Continue );
      return;
    }
 
    // 如果手动删除一个元素,事务名称为 'Delete Selection'
    if( transactionName.Equals( "Delete Selection" ) )
    {
      foreach( FailureMessageAccessor fma in fmas )
      {
        // 模拟手动单击"Remove Link"按钮
        failuresAccessor.ResolveFailure( fma );
 
        // 模拟手动单击"Ok"按钮
        //failuresAccessor.DeleteWarning(fma);         
      }
      e.SetProcessingResult( FailureProcessingResult.ProceedWithCommit );
 
      return;
    }
 
    e.SetProcessingResult( FailureProcessingResult.Continue );
  }
}

以上代码展示了两种处理警告的方式。没有被注释掉的那部分代码是其中一个方式:即解决该警告,而后被链接模型和被链接文件都被删除。如果你注释掉代码

failuresAccessor.ResolveFailure(fma)同时取消对代码failuresAccessor.DeleteWarning(fma)的注释,被链接模型依然会被删除但是被链接文件将保留。

重现这个问题的步骤如下:
1. 使用以上代码创建一个外部命令
2. 在 Revit 中创建一个新文档
3. 运行外部命令来注册失败处理器
4. 在新文档中导入模型
5. 使用 Revit“删除”命令删除被链接的模型

警告预处理
接下来我们聊聊如何预处理警告。我们只需要注册一个实现了 IFailuresPreprocessor 接口的类到事务中就可以了。

[TransactionAttribute( TransactionMode.Manual )]
[RegenerationAttribute( RegenerationOption.Manual )]
public class FailureHandle : IExternalCommand
{
  public Result Execute(
    ExternalCommandData commandData,
    ref string messages,
    ElementSet elements )
  {
    UIApplication app = commandData.Application;
    Document doc = app.ActiveUIDocument.Document;
 
    Transaction trans = new Transaction( doc, "DeleteLinkedModel" );
 
    trans.Start();
 
    FailureHandlingOptions options = trans.GetFailureHandlingOptions();
 
    MyPreProcessor preproccessor = new MyPreProcessor();
 
    options.SetFailuresPreprocessor( preproccessor );
    trans.SetFailureHandlingOptions( options );
 
    Selection sel = app.ActiveUIDocument.Selection;
 
    Reference ref1 = sel.PickObject( ObjectType.Element, "Please pick a linked model instance" );
 
    Element elem = ref1.Element;
 
    doc.Delete( elem );
 
    trans.Commit();
 
    return Result.Succeeded;
  }
}
 
/// <summary>
/// 定义失败预处理器
/// </summary>
public class MyPreProcessor : IFailuresPreprocessor
{
  FailureProcessingResult IFailuresPreprocessor.PreprocessFailures( FailuresAccessor failuresAccessor )
  {
    String transactionName = failuresAccessor.GetTransactionName();
 
    IList<FailureMessageAccessor> fmas = failuresAccessor.GetFailureMessages();
 
    if( fmas.Count == 0 )
    {
      return FailureProcessingResult.Continue;
    }
 
    // 这里我们假设已经知道了事务的名称
 
    if( transactionName.Equals( "DeleteLinkedModel" ) )
    {
      foreach( FailureMessageAccessor fma in fmas )
      {
        // 模拟手动单击"Remove Link"按钮
        failuresAccessor.ResolveFailure( fma );
 
        // 模拟手动单击"OK"按钮
        //failuresAccessor.DeleteWarning( fma );         
      }
 
      return FailureProcessingResult.ProceedWithCommit;
    }
    return FailureProcessingResult.Continue;
  }
}

失败预处理只适用于事务动作导致的失败。在上面的例程中,我们先选中被链接模型然后在事务中删除它。可以看到核心代码和之前的事件处理机制类似。


本文只是对失败处理做简单介绍,Revit 2011 SDK 中有例程 ErrorHandling 展示了更多的细节。当然你也可以在开发文档的第26章找到详细叙述。
### 使用 FastAPI 部署和调用 Qwen2.5-Coder-7B-Instruct 模型 #### 安装依赖库 为了能够顺利运行并部署该模型,需安装必要的 Python 库。这包括 `transformers` 和 `torch` 等用于加载预训练模型及其权重文件;以及 `fastapi` 及其 Uvicorn 服务器来创建 API 接口。 ```bash pip install transformers torch fastapi uvicorn ``` #### 加载模型 通过 Hugging Face Transformers 库可以方便地加载 Qwen2.5-Coder-7B-Instruct 模型。具体实现如下: ```python from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-Coder-7B-Instruct")[^1] model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-Coder-7B-Instruct", trust_remote_code=True) ``` #### 创建 FastAPI 应用程序 定义一个简单的 FastAPI 应用来接收 POST 请求并将输入文本传递给已加载的模型进行推理处理。 ```python from fastapi import FastAPI, Request import json app = FastAPI() @app.post("/predict/") async def predict(request: Request): data = await request.json() input_text = data.get('input', '') inputs = tokenizer(input_text, return_tensors="pt") outputs = model.generate(**inputs) result = tokenizer.decode(outputs[0], skip_special_tokens=True) response_data = {"output": result} return JSONResponse(content=response_data) ``` 此部分代码实现了从 HTTP 请求中获取用户提交的数据作为模型输入,并返回由模型生成的结果字符串。 #### 启动服务 最后一步是在本地环境中启动 FastAPI Web 服务器实例以便测试接口功能。 ```bash uvicorn main:app --reload ``` 这里假设上述所有代码保存在一个名为 `main.py` 文件内,则可以通过命令行执行以上指令开启开发模式下的自动重载功能的服务监听。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值