Announcement

Collapse
No announcement yet.

Problem mit Threads in modalen Fenstern

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem mit Threads in modalen Fenstern

    Hallo,

    ich habe folgendes Problem:

    In meiner Anwendung soll ein größerer Vorgang ablaufen, der erfordert, dass der Benutzer in der Zwischenzeit keine weiteren Aktionen vornimmt. Aus diesem Grund habe ich ein modales Fenster implementiert, in dem sich ein Start-Knopf für diesen Vorgang befindet. Klickt man darauf, wird ein Worker-Thread gestartet, in dem dieser Vorgang abgearbeitet wird. Den Thread benutze ich, damit die Oberfläche während dieser Aktion nicht "tot" ist und so auch einen Fortschritt anzeigen kann.

    Leider gibt es bei dieser Konstruktion das Problem, dass aus irgendeinem Grund nach dem Starten des Thread das Dialogfenster seinen modalen Status verliert. D.h. das darunterliegende Hauptfenster wird auf einmal bedienbar.

    Ich kann jedoch nicht sagen, welcher Programmabschnitt dieses Verhalten verursacht. Der Worker-Thread arbeitet einen ziemlich komplexen Prozeß ab (incl. COM-Interop) und in kleineren Szenarios konnte ich das Problem nicht reproduzieren.

    Kann mir jemand einen Tip geben, wodurch ein modales Dialogfenster plötzlich nicht-modal werden könnte? Jede Hilfe ist willkommen.

    Vielen Dank im Vorraus.


    Gruß,

    Ultru

  • #2
    Bitte mal den Code zeigen wie du den Thread in dieser Form startest und das drumherum in dieser Form (Form Schließen, anzeigen etc.). Vermutlich sieht man da schon was schief läuft.

    Comment


    • #3
      Hier ist meine modale Form, die das Hauptfenster blockiert solange die Operation läuft. Die Methode Execute bekommt ein Delegate zur auszuführenden Operation übergeben, startet den Thread und zeigt anschließend die Form mit ShowDialog an, bis der Thread beendet ist oder abgebrochehn wird.

      Code:
      internal partial class ExecuteOperationForm : Form
      {
      	public ExecuteOperationForm()
      	{
      		InitializeComponent();
      	}
      
      	private bool showAbortWarning = false;
      
      	public bool ShowAbortWarning
      	{
      		get { return showAbortWarning; }
      		set { showAbortWarning = value; }
      	}
      
      	private ThreadStart threadStart;
      	private ThreadStart cancel;
      	private Thread thread;
      
      	public DialogResult Execute(IWin32Window parent, ThreadStart operation)
      	{
      		return Execute(parent, operation, null);
      	}
      
      	public DialogResult Execute(IWin32Window parent, ThreadStart operation, ThreadStart cancelOperation)
      	{
      		threadStart = operation;
      		cancel = cancelOperation;
      		thread = new Thread(new ThreadStart(ExecuteOperation));
      		thread.Name = Text;
      		thread.Start();
      
      		DialogResult result = ShowDialog(parent);
      		return result;
      	}
      
      	private void ExecuteOperation()
      	{
      		dialogResult = DialogResult.OK;
      
      		// Call the delegate which does the job
      		threadStart();
      
      		while (IsDisposed == false)
      		{
      			Thread.Sleep(100);
      
      			// Close the form automatically
      			if (InvokeRequired)
      				BeginInvoke(new ThreadStart(Exit));
      			else
      				Exit();
      		}
      	}
      
      	private DialogResult dialogResult = DialogResult.OK;
      
      	private void Exit()
      	{
      		DialogResult = dialogResult;
      		Close();
      	}
      
      	private void Abort()
      	{
      		if (showAbortWarning)
      		{
      			// Show abort warning message box
      			DialogResult res = MessageBox.Show(ParentForm, StringsTransfer.CancelDataTransferMsg, StringsTransfer.Warning, MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
      			if (res != DialogResult.Yes)
      				return;
      		}
      
      		btnAbort.Enabled = false;
      		lblStop.Visible = true;
      		lblWait.Visible = false;
      
      		// Call cancel operation
      		if (cancel != null)
      			cancel();
      
      		dialogResult = System.Windows.Forms.DialogResult.Abort;
      	}
      
      	private void btnAbort_Click(object sender, System.EventArgs e)
      	{
      		if ((thread == null) || (thread.IsAlive == false))
      		{
      			dialogResult = DialogResult.Abort;
      			Close();
      		}
      		else
      			Abort();
      	}
      
      	private void timer_Tick(object sender, System.EventArgs e)
      	{
      		DialogResult res = MessageBox.Show(this, StringsTransfer.AbortTimeoutMsg, StringsTransfer.AbortTimeoutTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
      		if (res == DialogResult.Yes)
      			return;
      
      		timer.Enabled = false;
      		dialogResult = System.Windows.Forms.DialogResult.Abort;
      		Close();
      	}
      
      	private void ExecuteOperationForm_FormClosed(object sender, FormClosedEventArgs e)
      	{
      		timer.Enabled = false;
      	}
      }

      Comment

      Working...
      X