{"record":{"id":"486d6f0fc63838a6","repo":"babalae/better-genshin-impact","slug":"raw-input-486d6f","errorCode":null,"errorMessage":"Raw Input 初始化已取消。","messagePattern":"Raw Input 初始化已取消。","errorType":"exception","errorClass":"OperationCanceledException","httpStatus":null,"severity":"warning","filePath":"BetterGenshinImpact/Core/Monitor/RawInputMonitor.cs","lineNumber":237,"sourceCode":"    }\n\n    private void RunMessageLoop(RawInputThreadContext context)\n    {\n        try\n        {\n            context.Dispatcher = Dispatcher.CurrentDispatcher;\n            context.HwndSource = new HwndSource(new HwndSourceParameters(\"BetterGI RawInput Monitor\")\n            {\n                ParentWindow = HwndMessage,\n                WindowStyle = 0\n            });\n            context.HwndSource.AddHook(WindowProc);\n\n            RegisterRawInput(context);\n            context.Registered = true;\n            if (Volatile.Read(ref context.StopRequested) != 0)\n            {\n                throw new OperationCanceledException(\"Raw Input 初始化已取消。\");\n            }\n\n            context.InitializationSucceeded = true;\n            context.Initialized.Set();\n\n            Dispatcher.Run();\n        }\n        catch (Exception ex)\n        {\n            if (!context.InitializationSucceeded)\n            {\n                context.InitializationException = ex;\n                context.Initialized.Set();\n            }\n            Logger.LogError(ex, \"Raw Input 消息窗口异常终止\");\n        }\n        finally\n        {","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Core/Monitor/RawInputMonitor.cs#L219-L255","documentation":"On the RawInput worker thread, after registering devices but before signaling success, the code checks the StopRequested flag; if a stop was requested concurrently it throws OperationCanceledException('Raw Input 初始化已取消。'). This prevents partially-initialized state from being reported as ready and ensures a concurrent Stop() cleanly aborts startup.","triggerScenarios":"Calling Start() then immediately Stop() before the worker finishes setup; rapid enable/disable toggling of relative-mouse monitoring; the monitor being stopped during app shutdown while a previous Start is mid-flight.","commonSituations":"UI toggle flipped quickly; configuration change triggering a restart; shutdown racing with a fresh start. This is often benign (expected cancellation) rather than a fault.","solutions":["Treat OperationCanceledException from Start as non-fatal: log at debug/trace and continue.","Avoid starting and immediately stopping the monitor; debounce UI toggles.","Serialize Start/Stop with a lock or a single-threaded scheduler."],"exampleFix":"// before\nmonitor.Start();\n\n// after\ntry\n{\n    monitor.Start();\n}\ncatch (OperationCanceledException)\n{\n    // expected when Start races with Stop; safe to ignore\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try\n{\n    monitor.Start();\n}\ncatch (OperationCanceledException)\n{\n    // Start raced with Stop; expected and safe to ignore\n    logger.LogDebug(\"RawInput 启动被取消\");\n}","preventionTips":["Debounce Start/Stop toggles in the UI.","Serialize monitor lifecycle calls through a single scheduler.","Treat OperationCanceledException from Start as non-fatal."],"tags":["rawinput","cancellation","race","monitor"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}