/ / Qual è lo schema accettato di uccidere le attività in background in un'app WinForms - .net, winforms, backgroundworker, dispose

Qual è lo schema accettato di uccidere le attività in background in un'app WinForms - .net, winforms, backgroundworker, dispose

Ho ottenuto un'applicazione .net WinForms. Ho un UserControl che viene istanziato in base all'azione dell'utente - dopo l'istanziazione, esegue alcune attività dispendiose in termini di tempo su un thread in background (usando BackgroundWorker), mentre mostra l'animazione rotante ajaxy. L'utente può fare clic in qualsiasi momento, quindi fare nuovamente clic sul controllo utente (che ricomincerà da capo il thread in background).

Quando l'utente fa clic, voglio disporre di UserControl e di tutte le risorse in esso contenute (incluso il thread in background). Qual è il modo migliore per fare questo?

risposte:

1 per risposta № 1

Chiama il metodo CancelAsync su BackgroundWorker e attendi che termini. Costruisci il tuo codice di lavoro in modo che controlli frequentemente il flag di annullamento.

Se non ci sono effetti collaterali negativi se ilthread continua a funzionare per un po 'e non farà in alcun modo riferimento al controllo utente o ad alcuna risorsa in esso contenuta, è possibile disporre del controllo utente dopo aver richiesto la terminazione del thread.

EDIT: codice demo

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
public partial class FrmMain : Form
{
public FrmMain()
{
InitializeComponent();
}

private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("BG Done");
}

private void btnStart_Click(object sender, EventArgs e)
{
bg.WorkerSupportsCancellation = true;
bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
bg.DoWork += new DoWorkEventHandler(bg_DoWork);
bg.RunWorkerAsync();
}

void bg_DoWork(object sender, DoWorkEventArgs e)
{
int i=0;

while (!bg.CancellationPending)
{
lblStatus.BeginInvoke((MethodInvoker) delegate { lblStatus.Text = i + " sec."; });
System.Threading.Thread.Sleep(1000);
i++;
}

lblStatus.BeginInvoke((MethodInvoker)delegate { lblStatus.Text = "CANCEL"; });
}

private void btnStop_Click(object sender, EventArgs e)
{
bg.CancelAsync();
while (bg.IsBusy) // For real code limit max wait time in while loop
{
System.Threading.Thread.Sleep(50);
Application.DoEvents();
}
this.Close();
}
}
}


namespace WindowsFormsApplication1
{
partial class FrmMain
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Windows Form Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.bg = new System.ComponentModel.BackgroundWorker();
this.btnStart = new System.Windows.Forms.Button();
this.btnStop = new System.Windows.Forms.Button();
this.lblStatus = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// bg
//
this.bg.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.bg_RunWorkerCompleted);
//
// btnStart
//
this.btnStart.Location = new System.Drawing.Point(39, 13);
this.btnStart.Name = "btnStart";
this.btnStart.Size = new System.Drawing.Size(75, 23);
this.btnStart.TabIndex = 0;
this.btnStart.Text = "Start";
this.btnStart.UseVisualStyleBackColor = true;
this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
//
// btnStop
//
this.btnStop.Location = new System.Drawing.Point(39, 42);
this.btnStop.Name = "btnStop";
this.btnStop.Size = new System.Drawing.Size(75, 23);
this.btnStop.TabIndex = 1;
this.btnStop.Text = "Stop";
this.btnStop.UseVisualStyleBackColor = true;
this.btnStop.Click += new System.EventHandler(this.btnStop_Click);
//
// lblStatus
//
this.lblStatus.AutoSize = true;
this.lblStatus.Location = new System.Drawing.Point(39, 72);
this.lblStatus.Name = "lblStatus";
this.lblStatus.Size = new System.Drawing.Size(73, 13);
this.lblStatus.TabIndex = 2;
this.lblStatus.Text = "(Not Running)";
//
// FrmMain
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(423, 136);
this.Controls.Add(this.lblStatus);
this.Controls.Add(this.btnStop);
this.Controls.Add(this.btnStart);
this.Name = "FrmMain";
this.Text = "Main";
this.ResumeLayout(false);
this.PerformLayout();

}

#endregion

private System.ComponentModel.BackgroundWorker bg;
private System.Windows.Forms.Button btnStart;
private System.Windows.Forms.Button btnStop;
private System.Windows.Forms.Label lblStatus;
}
}

1 per risposta № 2

Potresti voler agganciare il Evento modificato. Chiedi al tuo lavoratore di invocare questo evento ogni volta che può essere fermato senza perdere lavoro. Ora con questo è possibile memorizzare lo stato corrente dell'attività impostando il valore in ProgressChangedEventArgs e poi puoi ricominciare da dove eri rimasto senza perdere lavoro.