l versC#多线程问题

时间:2017-11-01 11:27:35

标签: c# multithreading user-interface

在文件复制线程运行时,我无法让ui线程更新ui。我的最终目标是让动画继续旋转,直到大文件副本最终完成,让用户知道程序没有被冻结。这是一个非常简单的服务器到服务器文件复制程序。

有人能告诉我我做错了吗?

enter image description here Simple Windows Form

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
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void ResetProgress()
        {
            lblStep1.Image = null;
        }

        private void SetupProgress()
        {
            lblStep1.Image = global::animation1.Properties.Resources.animation;
        }

        private void fileCopy()
        {
            File.Copy("large file source", "large file destination", true);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            lblStep1.Image = global::animation1.Properties.Resources.animation;
        }

        private async void button1_Click(object sender, EventArgs e)
        {
            SetupProgress();
            await Task.Run(() => fileCopy());
            ResetProgress();
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            // unhandled currently
        }
    }
}

*原始版本*

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();
        }
    }

}

2 个答案:

答案 0 :(得分:2)

不要在点击处理程序中睡觉。这会冻结UI线程。让时钟处理程序退出。在您的文件复制线程中,当副本不是时。使用Invoke(或BeginInvoke)使完成的消息框在UI线程上弹出。

答案 1 :(得分:0)

尝试这种古老的风格

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();