Member 13462842 Ответов: 3

Как я могу нажать 2-ю кнопку, когда button1 все еще работает


       private void button1_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < 1000000; i++)
            {
                label1.Text = i.ToString();
            }
           
        }

        private void button2_Click(object sender, EventArgs e)
        {
            label1.Text = 0.ToString();
        }</pre

After i press button1, i is increasing and button2 is Locked until i is finished.
how can i press button2 at anytime?

What I have tried:

<pre>      private void button1_Click(object sender, EventArgs e)
        {
            Thread th1 = new Thread(Increment);
            th1.Start();
           
        }
        private void Increment()
        {
            for (int i = 0; i < 10000; i++)
            {
                label1.Text = i.ToString();
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            reset();
        }
        private void reset()
        {
            label1.Text = 0.ToString();
        }

EZW

Может быть, есть функция для кнопки one в потоке?

3 Ответов

Рейтинг:
22

Dave Kreskowiak

Ты не можешь. У вас есть поток пользовательского интерфейса, связанный с выполнением всей работы в обработчике button1. Пока этот метод не вернется, пользовательский интерфейс не сможет перекрасить себя (вот почему ваша метка не показывает значение при ее изменении) и не сможет реагировать на события мыши и клавиши.

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

Читать это: Как сделать Потокобезопасные вызовы элементов управления Windows Forms | Microsoft Docs[^]


Рейтинг:
15

Perić Željko

Привет,
эта проблема была интересна мне, когда я изучал C#, и вот мое решение :

Форму mainform.в CS

using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace Buttons_and_Threading
{
	/// <summary>
	/// Description of MainForm.
	/// Program code below needs two buttons and one label
	/// Initial buttons fore color should be set to green
	/// it needs .net framework 4.0 to run perfectly
	/// </summary>
	public partial class MainForm : Form
	{
		public MainForm()
		{
			//
			// The InitializeComponent() call 
			// is required for Windows Forms designer support.
			//
			InitializeComponent();
		}
		
		#region-   Parallel process methods and variables   -
		
		Thread Parallel;
		int i;
		
		protected delegate void Refresh_Data(string Text);
		
		void Button_1()
		{
			for (i = 0; i < 1000000; i++)
			{
				
				if(label1.InvokeRequired)
				{
					Refresh_Data refresh = Refresh_Label_1_Text;
					Invoke(refresh,i.ToString());
				}
				
			}
		}
		
		void Initialize_and_Start_New_Thread()
		{
			Parallel = new Thread(Button_1);
			Parallel.Start();
		}
		
		void Stop_Thread()
		{
			Parallel.Abort();
			while(Parallel.ThreadState != ThreadState.Aborted)
			{
				
			}
		}
		
		void Refresh_Label_1_Text(string Text)
		{
			label1.Text = Text;
		}
		
		void MainFormFormClosing(object sender, 
		                         System.Windows.Forms.FormClosingEventArgs e)
		{
			//
			// Before closing program check does parallel thread is
			// still running and stop it
			//
			
			if(Parallel.ThreadState != ThreadState.Aborted)
			{
				Parallel.Abort();
				while(Parallel.ThreadState != ThreadState.Aborted)
				{
					//
					// do nothing until parallel thread is stopped
					//
				}
			}
		}
		#endregion
		
		void Button1Click(object sender, EventArgs e)
		{
			if(button1.ForeColor == Color.ForestGreen)
			{
				//
				// change button text collor to red and 
				// start new parallel thread
				//
				button1.ForeColor = Color.Red;
				Initialize_and_Start_New_Thread();
			}
			else
			{
				//
				// Stop parallel thread and
				// change button text collor to green
				//
				Stop_Thread();
				button1.ForeColor = Color.ForestGreen;
			}
		}
		
		void Button2Click(object sender, EventArgs e)
		{
			//
			// reset counter to zero and
			// update label 1 text
			//
			i=0;
			if(label1.InvokeRequired)
			{
				Refresh_Data refresh = Refresh_Label_1_Text;
				Invoke(refresh,i.ToString());
			}
			
			else
				Refresh_Label_1_Text(i.ToString());
		}
	}
}



Главная.Форма.Дизайнер.в CS
namespace Buttons_and_Threading
{
	partial class MainForm
	{
		/// <summary>
		/// Designer variable used to keep track of non-visual components.
		/// </summary>
		private System.ComponentModel.IContainer components = null;
		
		/// <summary>
		/// Disposes resources used by the form.
		/// </summary>
		/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
		protected override void Dispose(bool disposing)
		{
			if (disposing) {
				if (components != null) {
					components.Dispose();
				}
			}
			base.Dispose(disposing);
		}
		
		/// <summary>
		/// This method is required for Windows Forms designer support.
		/// Do not change the method contents inside the source code editor. The Forms designer might
		/// not be able to load this method if it was changed manually.
		/// </summary>
		private void InitializeComponent()
		{
			this.button1 = new System.Windows.Forms.Button();
			this.button2 = new System.Windows.Forms.Button();
			this.label1 = new System.Windows.Forms.Label();
			this.SuspendLayout();
			// 
			// button1
			// 
			this.button1.ForeColor = System.Drawing.Color.ForestGreen;
			this.button1.Location = new System.Drawing.Point(14, 18);
			this.button1.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4);
			this.button1.Name = "button1";
			this.button1.Size = new System.Drawing.Size(264, 38);
			this.button1.TabIndex = 0;
			this.button1.Text = "Button 1";
			this.button1.UseVisualStyleBackColor = false;
			this.button1.Click += new System.EventHandler(this.Button1Click);
			// 
			// button2
			// 
			this.button2.ForeColor = System.Drawing.Color.ForestGreen;
			this.button2.Location = new System.Drawing.Point(14, 64);
			this.button2.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4);
			this.button2.Name = "button2";
			this.button2.Size = new System.Drawing.Size(264, 38);
			this.button2.TabIndex = 1;
			this.button2.Text = "Button 2";
			this.button2.UseVisualStyleBackColor = false;
			this.button2.Click += new System.EventHandler(this.Button2Click);
			// 
			// label1
			// 
			this.label1.Location = new System.Drawing.Point(20, 127);
			this.label1.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(158, 29);
			this.label1.TabIndex = 2;
			this.label1.Text = "Label 1";
			// 
			// MainForm
			// 
			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
			this.ClientSize = new System.Drawing.Size(292, 171);
			this.Controls.Add(this.label1);
			this.Controls.Add(this.button2);
			this.Controls.Add(this.button1);
			this.Font = new System.Drawing.Font("Arial", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
			this.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4);
			this.MaximizeBox = false;
			this.MaximumSize = new System.Drawing.Size(300, 200);
			this.MinimizeBox = false;
			this.Name = "MainForm";
			this.Text = "Buttons and Threading";
			this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainFormFormClosing);
			this.ResumeLayout(false);
		}
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Button button2;
		private System.Windows.Forms.Button button1;
	}
}


Попробуйте научиться работать с делегатами, в codeproject есть много статей на эту тему.

Всего наилучшего,
Желько Перич


Рейтинг:
11

BillWoodruff

Да, вам нужна резьба, и самый простой способ ее использовать-это использовать BackgroundWorker. CodeProject - ваш друг: [^], [^], [^]