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

物理模拟运行时非中断类问题与警告的处理方案咨询

物理模拟应用的三类问题解决方案

针对你提到的物理模拟应用中与UI解耦的两类问题,以下是具体实现方案:


案例3:非暂停警告的无侵入式收集方案

实现思路

使用AsyncLocal<WarningsHandler>实现上下文隔离的警告收集,既避免依赖注入对方法签名的污染,又能区分不同模拟实例的警告:

  • AsyncLocal绑定当前异步执行上下文,多实例并行运行时警告不会互相干扰
  • 核心代码通过静态访问点添加警告,无需修改构造函数或方法参数
  • UI层在启动模拟前初始化警告处理器并绑定到上下文,模拟结束后直接读取警告列表

修改后代码

// 静态上下文类,提供无侵入的警告访问入口
public static class WarningContext
{
    private static readonly AsyncLocal<WarningsHandler> _currentHandler = new();

    public static WarningsHandler Current
    {
        get => _currentHandler.Value ?? throw new InvalidOperationException("警告处理器未初始化");
        set => _currentHandler.Value = value;
    }

    // 简化核心代码的调用方式
    public static void AddWarning(string message) => Current.Add(message);
}

public class WarningsHandler
{
    public List<string> Warnings { get; init; } = new();

    public void Add(string warning) => Warnings.Add(warning);
}

public class Ui
{
    public void RunSimulationCommand()
    {
        var sim = new SimulationCore();
        var warningsHandler = new WarningsHandler();

        // 绑定当前模拟实例的警告处理器
        WarningContext.Current = warningsHandler;

        try
        {
            sim.RunSimulation();

            // 模拟结束后展示所有警告
            foreach (var warning in warningsHandler.Warnings)
            {
                MessageBox.Show(warning);
            }
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message); // 处理案例1的严重错误
        }
        finally
        {
            // 清理上下文,避免影响后续模拟
            WarningContext.Current = null;
        }
    }

    public bool ShowAlternativeInquiryMessage() => 
        MessageBox.Show("D为0,若预期此情况请点击Yes,否则点击No尝试替代计算", "", MessageBoxButton.YesNo) == MessageBoxResult.No;
}

public class SimulationCore
{
    public void RunSimulation() => PhysicsSimulationRunner.RunPhysics();

    public static class PhysicsSimulationRunner
    {
        public static void RunPhysics()
        {
            int a = 0;
            int b = 1 / a; // 案例1:抛出异常,由UI捕获

            int c = GetValueC();
            if (c > 1000)
            {
                // 无侵入添加警告,无需依赖注入
                WarningContext.AddWarning("C值超过1000");
            }

            int d = GetValueD();
            if (d == 0)
            {
                // 案例2的逻辑见下文
            }
        }

        public static int GetValueC() => 1001;
        public static int GetValueD() => 0;
        public static int GetValueDAlt() => 5;
    }
}

案例2:模拟暂停与用户交互的解耦方案

实现思路

采用回调委托+抽象交互契约实现解耦:

  • 核心模拟代码接受一个Func<SimulationRequest, object>类型的回调委托,该委托由UI层实现
  • 当需要用户交互时,核心代码创建抽象的交互请求对象,调用回调委托获取用户输入
  • 核心代码仅依赖抽象的交互请求模型,完全不耦合具体UI实现

修改后代码

// 抽象交互请求契约,核心代码仅依赖此类型
public abstract class SimulationRequest
{
    // 定义交互逻辑的执行入口,由UI层实现具体行为
    public abstract object Execute(Ui ui);
}

// 案例2的具体交互请求
public class AlternativeCalculationRequest : SimulationRequest
{
    public override object Execute(Ui ui) => ui.ShowAlternativeInquiryMessage();
}

public class Ui
{
    public void RunSimulationCommand()
    {
        var sim = new SimulationCore();
        var warningsHandler = new WarningsHandler();

        WarningContext.Current = warningsHandler;

        try
        {
            // 传递UI实现的交互回调给核心模拟
            sim.RunSimulation(request => request.Execute(this));

            foreach (var warning in warningsHandler.Warnings)
            {
                MessageBox.Show(warning);
            }
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        finally
        {
            WarningContext.Current = null;
        }
    }

    public bool ShowAlternativeInquiryMessage() => 
        MessageBox.Show("D为0,若预期此情况请点击Yes,否则点击No尝试替代计算", "", MessageBoxButton.YesNo) == MessageBoxResult.No;
}

public class SimulationCore
{
    // 核心模拟方法接受交互回调参数
    public void RunSimulation(Func<SimulationRequest, object> interactionCallback) => 
        PhysicsSimulationRunner.RunPhysics(interactionCallback);

    public static class PhysicsSimulationRunner
    {
        public static void RunPhysics(Func<SimulationRequest, object> interactionCallback)
        {
            int a = 0;
            int b = 1 / a;

            int c = GetValueC();
            if (c > 1000)
            {
                WarningContext.AddWarning("C值超过1000");
            }

            int d = GetValueD();
            if (d == 0)
            {
                // 创建交互请求,调用回调获取用户选择
                bool tryAlternative = (bool)interactionCallback(new AlternativeCalculationRequest());
                if (tryAlternative)
                {
                    d = GetValueDAlt();
                }
            }

            // 继续执行后续模拟逻辑
        }

        public static int GetValueC() => 1001;
        public static int GetValueD() => 0;
        public static int GetValueDAlt() => 5;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 22:42:03