Какова принятая схема уничтожения фоновых задач в приложении WinForms? - PullRequest
2 голосов
/ 13 января 2010

У меня есть приложение .net WinForms. У меня есть UserControl, который создается на основе действий пользователя - при создании он выполняет некоторые трудоемкие задачи в фоновом потоке (используя BackgroundWorker), отображая вращающуюся анимацию ajaxy. Пользователь может щелкнуть в любое время, а затем снова щелкнуть на пользовательском элементе управления (который снова запустит фоновый поток).

Когда пользователь щелкает, я хочу избавиться от UserControl и всех ресурсов, которые он содержит (включая фоновый поток). Каков наилучший способ сделать это?

Ответы [ 2 ]

1 голос
/ 13 января 2010

Вы можете подключиться к событию Progress Changed . Попросите вашего работника вызывать это событие всякий раз, когда оно может быть безопасно остановлено без потери работы. Теперь вы можете сохранить текущее состояние задачи, установив значение в ProgressChangedEventArgs , а затем перезапустить с того места, на котором остановились, без потери работы.

1 голос
/ 13 января 2010

Вызовите метод CancelAsync на BackgroundWorker и дождитесь его завершения. Создайте свой рабочий код, чтобы он часто проверял флаг отмены.

Если нет никаких отрицательных побочных эффектов, если поток продолжает работать некоторое время, и он никоим образом не будет ссылаться на пользовательский элемент управления или любой ресурс, которым он владеет, вы можете избавиться от пользовательского элемента управления после запроса завершения потока .

РЕДАКТИРОВАТЬ: Демо-код

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;
    }
}
...