ios 异步ui
Mulithreading is a wonderful concept but it is one of the most complex way to achieve a task. Microsoft had provided probably the most efficient way to handle this problem by using async calls and thread pool. This provides an easy way to handle more than one task in an efficient way. But the biggest problem is thread creation and disposal of thread in this programming scenario. A common problem we are facing with UI programming is we are executing a task which takes a long time.
Mulithreading是一个很棒的概念,但是它是完成任务的最复杂的方法之一。 Microsoft通过使用异步调用和线程池提供了可能最有效的方法来解决此问题。 这提供了一种以有效方式处理多个任务的简便方法。 但是最大的问题是在此编程方案中线程的创建和线程的处置。 UI编程面临的一个常见问题是我们正在执行需要很长时间的任务。
And if we are trying to do the same in Main Thread of application it freezes the UI until the completion of job. For example in the given program we are trying to run infinite loop and trying the display the count on textbox
而且,如果我们尝试在应用程序的主线程中执行相同的操作,则它将冻结UI直到作业完成。 例如,在给定程序中,我们尝试运行无限循环并尝试在文本框上显示计数
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
private TextBox textBox1;
private Button btnStart;
public Form1()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.btnStart = new System.Windows.Forms.Button();
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// btnStart
//
this.btnStart.Location = new System.Drawing.Point(134, 27);
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);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(12, 29);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(100, 20);
this.textBox1.TabIndex = 1;
//
// Form1
//
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.btnStart);
this.Name = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
/// <summary>
/// Updates the textbox
/// </summary>
/// <param name="i">Value to be updated</param>
private void UpdateTextBox(int i)
{
textBox1.Text = i.ToString();
}
/// <summary>
/// Start counting
/// </summary>
/// <param name="i">Intial value</param>
private void Count(int i)
{
while (true)
{
i++;
UpdateTextBox(i);
}
}
private void btnStart_Click(object sender, EventArgs e)
{
Count(0);
}
}
}
One of the better ways to solve this is pushing the time consuming task to a different thread and update the UI with callback method.
解决此问题的更好方法之一是将耗时的任务推送到其他线程,并使用回调方法更新UI。
One of best way to achieve this is by using BackgroundWorker class
实现此目的的最佳方法之一是使用BackgroundWorker类
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
private TextBox textBox1;
private System.ComponentModel.BackgroundWorker backgroundWorker1;
private Button btnStart;
public Form1()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.btnStart = new System.Windows.Forms.Button();
this.textBox1 = new System.Windows.Forms.TextBox();
this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
this.SuspendLayout();
//
// btnStart
//
this.btnStart.Location = new System.Drawing.Point(134, 27);
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);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(12, 29);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(100, 20);
this.textBox1.TabIndex = 1;
//
// backgroundWorker1
//
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
//
// Form1
//
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.btnStart);
this.Name = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
/// <summary>
/// Updates the textbox
/// </summary>
/// <param name="i">Value to be updated</param>
private void UpdateTextBox(int i)
{
textBox1.Text = i.ToString();
}
/// <summary>
/// Start counting
/// </summary>
/// <param name="i">Intial value</param>
private void Count(int i)
{
while (true)
{
i++;
this.Invoke(new Action<int>((x) => textBox1.Text = x.ToString()), i);
}
}
private void btnStart_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
Count(0);
}
}
}
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
private TextBox textBox1;
private Button btnStart;
public Form1()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.btnStart = new System.Windows.Forms.Button();
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// btnStart
//
this.btnStart.Location = new System.Drawing.Point(134, 27);
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);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(12, 29);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(100, 20);
this.textBox1.TabIndex = 1;
//
// Form1
//
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.btnStart);
this.Name = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
private void UpdateTextBox(int i)
{
textBox1.Text = i.ToString();
}
private void Count(int i)
{
while (true)
{
i++;
this.Invoke(new Action<int>((x) => textBox1.Text = x.ToString()), i);
}
}
private void btnStart_Click(object sender, EventArgs e)
{
int i = 0;
new Action<int>(Count).BeginInvoke(i, null, null);
}
}
}
And similar thing can be achieved with Task Class from .net 4.0 onwards.
从.net 4.0开始,使用Task Class也可以实现类似的目的。
using System;
using System.Timers;
using System.Threading;
using System.Windows.Forms;
using System.Threading.Tasks;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
private TextBox textBox1;
private Button btnStart;
public Form1()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.btnStart = new System.Windows.Forms.Button();
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// btnStart
//
this.btnStart.Location = new System.Drawing.Point(134, 27);
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);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(12, 29);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(100, 20);
this.textBox1.TabIndex = 1;
//
// Form1
//
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.btnStart);
this.Name = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
private void UpdateTextBox(int i)
{
textBox1.Text = i.ToString();
}
private void Count()
{
int i=0;
while (true)
{
this.Invoke(new Action<int>((x) => textBox1.Text = x.ToString()), i++);
}
}
private void btnStart_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(new Action(Count));
}
}
}
and making it more compact:
并使其更紧凑:
using System;
using System.Timers;
using System.Threading;
using System.Windows.Forms;
using System.Threading.Tasks;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
private TextBox textBox1;
private Button btnStart;
public Form1()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.btnStart = new System.Windows.Forms.Button();
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// btnStart
//
this.btnStart.Location = new System.Drawing.Point(134, 27);
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);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(12, 29);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(100, 20);
this.textBox1.TabIndex = 1;
//
// Form1
//
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.btnStart);
this.Name = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
private void btnStart_Click(object sender, EventArgs e)
{
Task.Factory.StartNew((Action)delegate()
{
int i = 0;
while (true)
{
this.Invoke(new Action<int>((x) => textBox1.Text = x.ToString()), i++);
}
});
}
}
}
Please note that in all these method Thread is taken from ThreadPool
请注意,在所有这些方法中,线程均来自ThreadPool
翻译自: https://www.experts-exchange.com/articles/13575/Asynchronous-programming-with-UI.html
ios 异步ui