Xamarin.Android调用alert.Dispose()后AlertDialog未消失问题
Let’s break down why this is happening and how to fix it.
First, here’s the original code you shared:
AlertDialog.Builder alertConfirmTransfer = new AlertDialog.Builder(this); alertConfirmTransfer.SetMessage("Some message"); alertConfirmTransfer.SetPositiveButton("YES", delegate { alertConfirmTransfer.Dispose(); }); alertConfirmTransfer.SetNegativeButton("NO", delegate { alertConfirmTransfer.Dispose(); }); Dialog dialogConfirmTransfer = alertConfirmTransfer.Create(); dialogConfirmTransfer.Show();
The problem arises when you add a time-consuming try-catch block right after alertConfirmTransfer.Dispose(); in the YES button delegate: the dialog stays visible even though you’ve called the dispose method.
Why This Happens
Button click delegates run on the UI thread, which is responsible for all interface updates—including hiding the dialog. If you block this thread with a long-running operation (like your try-catch logic), the UI thread can’t process the dialog’s close request immediately. The Dispose() call is made, but the UI can’t refresh to reflect that change until the time-consuming code finishes executing.
The Fix: Offload Heavy Work to a Background Thread
To resolve this, you need to separate the dialog closure (a quick UI thread task) from your long-running logic (which should run on a background thread). Here’s how to adjust your code using async/await and Task.Run:
AlertDialog.Builder alertConfirmTransfer = new AlertDialog.Builder(this); alertConfirmTransfer.SetMessage("Some message"); // Use an async delegate for the positive button to enable await alertConfirmTransfer.SetPositiveButton("YES", async (sender, args) => { // Close the dialog first—this runs on the UI thread and happens immediately alertConfirmTransfer.Dispose(); try { // Move time-consuming work to a background thread pool thread await Task.Run(() => { // Your long-running logic goes here (e.g., heavy computation, file I/O, network calls) }); // If you need to update the UI after the work finishes, switch back to the UI thread RunOnUiThread(() => { // Example: Show a success message or update UI elements }); } catch (Exception ex) { // Handle exceptions, and ensure any UI-related error handling runs on the UI thread RunOnUiThread(() => { // Example: Show an error toast or log the issue }); } }); alertConfirmTransfer.SetNegativeButton("NO", (sender, args) => alertConfirmTransfer.Dispose()); Dialog dialogConfirmTransfer = alertConfirmTransfer.Create(); dialogConfirmTransfer.Show();
Key Notes
- Async Delegate: Using
async (sender, args)lets us useawait, which keeps the UI thread responsive while waiting for the background task to complete. - Task.Run: This sends your heavy logic to a separate thread, so the UI thread isn’t blocked and can immediately process the dialog’s closure.
- RunOnUiThread: Any UI updates (like success/error messages) must be done on the UI thread—this method ensures those operations are routed correctly.
By splitting these tasks, you ensure the dialog disappears right when the user clicks YES, while your time-consuming code runs in the background without freezing the interface.
内容的提问来源于stack exchange,提问作者Profile2ForStack

