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

Unity中调用外部EXE时WaitForExit阻塞主程序的问题咨询

Fixing Unity Freeze When Running an External EXE That Needs Microphone Input

Hey there! I totally get your frustration—you’re trying to launch an external EXE in Unity that relies on microphone input, but using WaitForExit() locks up your Unity app until the EXE closes. That’s no good when you need Unity to keep handling updates, UI, or other tasks in the background. Let’s break down how to solve this without blocking the main thread.

Why WaitForExit() Causes the Freeze

Unity runs almost all critical operations (like rendering, input handling, and MonoBehaviour updates) on its main thread. When you call WaitForExit(), it blocks this thread entirely until the external process finishes. That’s why your app becomes unresponsive—Unity can’t do anything else until the EXE closes.

Solution 1: Use the Process.Exited Event

This approach lets you listen for when the EXE exits without blocking the main thread. We’ll enable event raising for the process and hook into its Exited callback.

Here’s a ready-to-use script example:

using UnityEngine;
using System.Diagnostics;

public class ExternalExeRunner : MonoBehaviour
{
    // Call this method to start your EXE (e.g., from a UI button click)
    public void LaunchExternalExe()
    {
        var process = new Process();
        process.StartInfo.FileName = "path/to/your/exe.exe";
        // Add any other StartInfo config you need (working directory, arguments, etc.)
        process.StartInfo.UseShellExecute = false;
        
        // Critical: Enable event raising so we get notified when the EXE exits
        process.EnableRaisingEvents = true;
        // Hook up the exit callback
        process.Exited += OnExeExited;
        
        // Start the process—Unity's main thread won't block here!
        process.Start();
    }

    private void OnExeExited(object sender, System.EventArgs e)
    {
        var finishedProcess = sender as Process;
        if (finishedProcess == null) return;

        // Get the exit code if you need it
        int exitCode = finishedProcess.ExitCode;
        
        // Important: Unity API calls (like Debug.Log or UI updates) must run on the main thread!
        // Use Invoke to jump back to the main thread for these operations
        Invoke(() => 
        {
            Debug.Log($"External EXE exited with code: {exitCode}");
            // Add your post-exit logic here (e.g., update UI, trigger game events)
        }, 0);

        // Clean up process resources to avoid leaks
        finishedProcess.Dispose();
    }

    // Optional: Clean up if the MonoBehaviour is destroyed before the EXE exits
    private void OnDestroy()
    {
        // If you're keeping a reference to the process, check if it's still running and close it
        // (You'd need to store the process instance as a class variable for this)
    }
}

Key Notes for This Method:

  • The Exited callback runs on a background thread, never call Unity API methods directly here—always use Invoke() or a main thread dispatcher to handle Unity-specific logic.
  • Make sure your EXE has proper access to the microphone. If Unity is already using the mic, you might need to adjust microphone permissions or disable Unity’s mic usage temporarily while the EXE runs.

Solution 2: Use Async/Await with Background Threading

If you prefer working with async patterns, you can offload the WaitForExit() call to a background thread using Task.Run(), then await it without blocking Unity’s main thread.

Here’s how that looks:

using UnityEngine;
using System.Diagnostics;
using System.Threading.Tasks;

public class AsyncExeRunner : MonoBehaviour
{
    public async void LaunchExeAsync()
    {
        var process = new Process();
        process.StartInfo.FileName = "path/to/your/exe.exe";
        process.StartInfo.UseShellExecute = false;
        
        process.Start();

        // Wait for the EXE to exit on a background thread
        await Task.Run(() => process.WaitForExit());

        // After await, we're back on the main thread? Not always—play it safe with Invoke
        int exitCode = process.ExitCode;
        Invoke(() => 
        {
            Debug.Log($"EXE exited with code: {exitCode}");
            // Handle post-exit Unity logic here
        }, 0);

        process.Dispose();
    }
}

Why This Works:

Task.Run() moves the blocking WaitForExit() call to a separate thread, so Unity’s main thread stays free to handle updates. The await keyword pauses the async method until the task completes, but doesn’t block the rest of the app.

Important Reminders

  • Clean Up Process Resources: Always call Dispose() on the Process object once it’s done to avoid memory leaks.
  • Microphone Access Conflicts: If both Unity and the EXE need the microphone, you might need to release Unity’s mic capture before launching the EXE, then reinitialize it afterward.
  • Error Handling: Add try/catch blocks around process start/exit logic to handle cases where the EXE fails to launch or crashes unexpectedly.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:27:08