stw 发表于 2022-3-24 10:39:42

在异步方法中运行同步命令

您好,
我有一些异步方法(如web请求),需要在一系列命令之间调用。我需要子命令同步运行,因此无法使用CommandAsync(),因为子命令具有用户交互,我希望等待所有这些都完成(子命令例如可以获得选择集)
Autodesk.AutoCAD.Runtime。例外:eInvalidInput
示例:
   
    public static async void CmdTest()
    {
      var activeDoc = Application.DocumentManager.MdiActiveDocument;
      Editor editor = activeDoc.Editor;
      await Task.Delay(100);   // this could be e.g. some async web request in practice
      try
      {
            editor.Command("BCOUNT");// some dummy command
            editor.WriteMessage("finished CMD_TEST\n");
      }
      catch (Exception ex)
      {
            editor.WriteMessage("failed CMD_TEST\n");
      }
    }
原因是什么,如何解决
为完整起见,以下是一个工作和非工作命令()调用的两个堆栈:
>        test_autocad.dll!Tools.AutoCAD.CommandsTest.CmdTestWorking()
        accoremgd.dll!Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(System.Reflection.MethodInfo mi, object commandObject, bool bLispFunction)
        accoremgd.dll!Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(System.Reflection.MethodInfo mi, object commandObject, bool bLispFunction)
        accoremgd.dll!Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.Invoke()
               
        accore.dll!CCmdThroat::arxCallNativeFunction()
        accore.dll!Command::doCommand()
        accore.dll!runTheCommand()
        accore.dll!CommandProcessor::mainCmdLoop()
        accore.dll!CCmdThroat::Run()
        accore.dll!AcApAppImp::internalRun()
        accore.dll!AcApAppImp::run(void)
        acad.exe!00007ff764026c41()
        mfc140u.dll!00007ff8109a3840()
        acad.exe!00007ff764039602()
        kernel32.dll!00007ff859ca7034()
        ntdll.dll!00007ff85b822651()
>        test_autocad.dll!Tools.AutoCAD.CommandsTest.CmdTestFailing()
               
        mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)
        mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)
        mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run()
        mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.OutputAsyncCausalityEvents.AnonymousMethod__0()
        mscorlib.dll!System.Runtime.CompilerServices.TaskAwaiter.OutputWaitEtwEvents.AnonymousMethod__0()
        mscorlib.dll!System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.GetActionLogDelegate.AnonymousMethod__0()
        acpal.dll!00007fffe380d218()
        acpal.dll!00007fffe380d2e4()
        accore.dll!AcApAppImp::notifyMessagePreviewObservers(struct tagMSG &,bool)
        accore.dll!AcApApp::notifyMessagePreviewObservers(struct tagMSG &)
        acad.exe!CAcadApp::PreTranslateMessage()
        mfc140u.dll!AfxInternalPumpMessage()
        acad.exe!CAcadApp::PumpMessage(void)
        acad.exe!CAcadApp::runMessageLoop()
        accore.dll!AcApAppImp::runMessageLoop(void)
        accore.dll!win_event(void)
        accore.dll!CCmdThroat::select_device()
        accore.dll!CDig::digin()
        accore.dll!CAcCoreInput::GetRawInput()
        accore.dll!CAcCoreInput::egetdat()
        accore.dll!getCommandNameOrGripSelectionInput()
        accore.dll!CCmdThroat::Run()
        accore.dll!AcApAppImp::internalRun()
        accore.dll!AcApAppImp::run(void)
        acad.exe!CAcadApp::Run(void)
        mfc140u.dll!AfxWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow)
        acad.exe!__scrt_common_main_seh()
        kernel32.dll!BaseThreadInitThunk()
        ntdll.dll!RtlUserThreadStart()

**** Hidden Message *****

CADbloke 发表于 2022-3-25 03:45:46

原因是AutoCAD运行在UI线程上,就像石器时代的大多数遗留软件一样
修复可能涉及将命令添加到一个列表中,该列表在异步例程返回且应用程序处于静止状态后在主线程上执行<你可以试试调度器。调用…我在打电话,所以我没有掌握语法。我猜这种方法是不可预测的,不可靠的。我不会相信它。

stw 发表于 2022-3-25 12:41:14

Application.DocumentManager.IsApplicationContext 似乎很合适。当它返回 true 时,我们不在命令上下文中,并且当我们已经在命令上下文中时,它似乎也总是返回 false。
页: [1]
查看完整版本: 在异步方法中运行同步命令