l versC#多线程问题
文件复制线程正在运行时,我无法让ui线程更新ui。我的最终目标是让动画继续旋转,直到大文件拷贝最终完成,让用户知道程序没有冻结。这是一个非常简单的服务器到服务器文件复制程序 有人能告诉我我做错了什么吗 *原始版本*l versC#多线程问题,c#,multithreading,user-interface,C#,Multithreading,User Interface,文件复制线程正在运行时,我无法让ui线程更新ui。我的最终目标是让动画继续旋转,直到大文件拷贝最终完成,让用户知道程序没有冻结。这是一个非常简单的服务器到服务器文件复制程序 有人能告诉我我做错了什么吗 *原始版本* using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; usi
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;
using System.Threading;
using System.IO;
using System.Threading.Tasks;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private Thread workItemsProducerThread;
private Thread workItemsCopyThread;
public Form1()
{
InitializeComponent();
}
private void ResetProgress()
{
lblStep1.Image = null;
}
private void SetupProgress()
{
this.BeginInvoke((MethodInvoker)delegate ()
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
});
}
private void fileCopy()
{
File.Copy("Large file source", "Large file destination", true);
this.BeginInvoke((MethodInvoker)delegate ()
{
MessageBox.Show("Done");
});
}
private void Form1_Load(object sender, EventArgs e)
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
}
private void btnStart_Click(object sender, EventArgs e)
{
this.workItemsProducerThread = new Thread(new ThreadStart(this.SetupProgress));
this.workItemsProducerThread.IsBackground = true;
this.workItemsProducerThread.Start();
this.SetupProgress();
this.workItemsCopyThread = new Thread(new ThreadStart(this.fileCopy));
this.workItemsCopyThread.IsBackground = true;
this.workItemsCopyThread.Start();
while (workItemsCopyThread.IsAlive)
{
Thread.Sleep(1000); // wait
}
MessageBox.Show("Done");
}
private void btnStop_Click(object sender, EventArgs e)
{
if (this.workItemsProducerThread != null)
{
this.workItemsProducerThread.Abort();
lblStep1.Image = global::animation1.Properties.Resources.animation;
}
}
private void btnTest_Click(object sender, EventArgs e)
{
fileCopy();
}
}
}不要在单击处理程序中睡觉。这会冻结UI线程。让时钟处理器退出。在文件复制线程中,当复制为“不”时。使用Invoke(或BeginInvoke)使完成消息框在UI线程上弹出 试试这种老式风格
private void SetupProgress()
{
Invoke((MethodInvoker) delegate
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
});
}
private Thread TDoSomeWork()
{
var t = new Thread(() => DoSomeWork());
t.Start();
return t;
}
TDoSomeWork();
如果我理解正确,我已经进行了上述更正,但仍然遇到相同的症状?没有理由在Task.Run和
async/await
可用时使用Invoke或threads。您需要从单击处理程序中删除:while isalive循环和messagebox。(异步更容易)相反,没有理由在另一个线程上运行SetupProgress。这是个坏主意。好吧,我试过这两个建议,症状仍然一样。我曾尝试从主UI运行SetupProgress,并将begininvoke替换为just invokes,但行为没有改变。@Jay这是因为代码太复杂了。您不需要线程、调用或中止。Henk Holterman的回答显示了使用内置任务编写此代码是多么容易。Run和async/await.Panagiotis,您介意试试我的示例,看看它是否适合您吗?fileCopy
应该是async
方法,并从任务
中移出,您不需要这里的线程池-它是IO方法,它们正是async
的目标。
private void SetupProgress()
{
Invoke((MethodInvoker) delegate
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
});
}
private Thread TDoSomeWork()
{
var t = new Thread(() => DoSomeWork());
t.Start();
return t;
}
TDoSomeWork();