babalae/better-genshin-impact · error · ArgumentNullException

内部视图模型对象为空

Error message

内部视图模型对象为空

What it means

ArgumentNullException thrown by Dispatcher.RunTask at line 134 when App.GetService<TaskSettingsPageViewModel>() returns null. This is NOT a script-author error — it indicates the WPF DI container has no TaskSettingsPageViewModel registered, or the call happened before the app/DI was built or after disposal. TaskSettingsPageViewModel supplies settings (AutoWood rounds, fight strategy) needed by several task branches.

Source

Thrown at BetterGenshinImpact/Core/Script/Dependence/Dispatcher.cs:134

    /// - AutoGeniusInvokation: 启动自动七圣召唤任务
    /// - AutoWood: 启动自动伐木任务
    /// - AutoFight: 启动自动战斗任务
    /// - AutoDomain: 启动自动秘境任务
    /// </param>
    /// <param name="customCt">自定义取消令牌,允许从JS控制任务取消</param>
    /// <exception cref="ArgumentNullException"></exception>
    /// <exception cref="ArgumentException"></exception>
    public async Task<object?> RunTask(SoloTask soloTask, CancellationToken? customCt = null)
    {
        if (soloTask == null)
        {
            throw new ArgumentNullException(nameof(soloTask), "独立任务对象不能为空");
        }

        var taskSettingsPageViewModel = App.GetService<TaskSettingsPageViewModel>();
        if (taskSettingsPageViewModel == null)
        {
            throw new ArgumentNullException(nameof(taskSettingsPageViewModel), "内部视图模型对象为空");
        }


        CancellationToken cancellationToken;

        if (customCt != null)
        {
            cancellationToken = customCt.Value;
        }
        else
        {
            // 如果没有自定义令牌,就使用全局令牌
            cancellationToken = CancellationContext.Instance.Cts.Token;
        }

        // 根据名称执行任务
        switch (soloTask.Name)
        {

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Gate script execution on TaskContext.Instance().IsInitialized (same check PlayMacro uses) before invoking RunTask.
  2. Ensure TaskSettingsPageViewModel is registered in the DI container at app startup.
  3. Do not call Dispatcher.RunTask from test/headless contexts; provide a test double or skip.
  4. If this fires intermittently, delay script start until the main UI is loaded.

Example fix

// before (C# / script host)
dispatcher.RunTask(soloTask); // may throw if DI not ready

// after (C# / script host)
if (!TaskContext.Instance().IsInitialized)
{
    throw new InvalidOperationException("Dispatcher.RunTask requires the app to be fully initialized.");
}
dispatcher.RunTask(soloTask);
Defensive patterns

Strategy: validation

Validate before calling

// C# host — gate script execution on app readiness
if (!TaskContext.Instance().IsInitialized)
    throw new InvalidOperationException("Cannot run tasks before the app is fully initialized.");

Prevention

When it happens

Trigger: A script runs RunTask before the WPF application finished initializing its service provider. Running the script from a unit test or headless harness that never registered TaskSettingsPageViewModel. The app is shutting down and the DI root has been disposed.

Common situations: Script triggered during early startup (before the main window / pages are constructed). DI registration for pages/viewmodels was removed or moved behind a condition. Integration test reused Dispatcher without spinning up the full app host.

Related errors


AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13). Data as JSON: /api/errors/7d5ff16114aadae3. Report an issue: GitHub.