0

假设我有任务 1:

private void Task1()
{
    //Here is some Code, could be any "longer" Task - 
    //For Example: Grab all words from a .txt File and fill in a List<String>
}

然后我还有另一个任务 2:

private void Task2(string word)
{
   //So lets say theres a Label on my WinForm..
   //Now While Task1 is grabbing the words, Task2 should fill a Label 
   //with the added 'word' (parameter) - (Task2 will be called from Task1
}

实际上,我不知道如何使这成为可能,或者最好的方法是什么。在 UI 上,我应该能够看到Label.Text变化(每个字)。所以我需要创建第二个线程?我怎么能这样做?也许有人可以帮助我,干杯

更新:

我现在用Backgroundworker尝试过,但有些东西似乎是错误的..它实际上不起作用,表单上没有任何反应

代码:

public void CreateAndSaveAMatch(DateTime date) //That method is being called several times
{   
    //HERE IS CODE, WHICH CREATES AND SAVES A MATCH

    // Start the asynchronous operation.
    backgroundWorker1.RunWorkerAsync(date);

}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{      
    backgroundWorker1.ReportProgress(0, Convert.ToDateTime(e.Argument).ToShortDateString());          
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    label1.Text = (string)e.UserState; //here on the Label I would like to show the Date
}
4

4 回答 4

2

用于BackgroundWorker报告第一个任务的进度。将此组件从工具箱拖到您的表单中,并订阅DoWorkProgressChanged事件。还将属性设置WorkerReportsProgresstrue. 然后异步启动你的第一个任务:

// this will execute code in `DoWork` event handler
backgroundWorker1.RunWorkerAsync();

下一步 - 使用userState对象传递处理过的单词:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{      
    // grab words in a loop and report progress
    backgroundWorker1.ReportProgress(0, word);
}

ProgressChanged最后一步 - 更新事件处理程序中的标签

void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    label1.Text += (string)e.UserState; // this is your grabbed word
}
于 2012-10-28T20:13:44.200 回答
2

好的,试试这个。这是一个简单的示例,将向您展示如何使用BackgroundWorker. 另请注意,还有许多其他解决方案。要使用此示例,请在只有一个按钮和一个标签的新项目中创建一个表单。另请注意,这是对其他正确答案的补充。

public partial class Form1 : Form
    {
        BackgroundWorker createAndSaveAMatchBGW;
        public Form1()
        {
            InitializeComponent();
            createAndSaveAMatchBGW = new BackgroundWorker();
            createAndSaveAMatchBGW.DoWork += new DoWorkEventHandler(createAndSaveAMatchBGW_DoWork);
            createAndSaveAMatchBGW.ProgressChanged += new ProgressChangedEventHandler(createAndSaveAMatchBGW_ProgressChanged);
            createAndSaveAMatchBGW.RunWorkerCompleted += new RunWorkerCompletedEventHandler(createAndSaveAMatchBGW_RunWorkerCompleted);
            createAndSaveAMatchBGW.WorkerReportsProgress = true;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            createAndSaveAMatchBGW.RunWorkerAsync(DateTime.Now);
        }

        void createAndSaveAMatchBGW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("BackgroundWorker finished");
        }

        void createAndSaveAMatchBGW_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            label1.Text = ((DateTime)e.UserState).ToString("ss");
        }

        void createAndSaveAMatchBGW_DoWork(object sender, DoWorkEventArgs e)
        {
            //BackgroundWorker does something for a 10 seconds, each second it Reports
            BackgroundWorker bgw = (BackgroundWorker)sender;
            DateTime dt = (DateTime) e.Argument;
            for (int i = 0; i < 10; i++)
            {
                Thread.Sleep(1000);
                dt = dt.AddSeconds(1);
                bgw.ReportProgress(0, dt);
            }
        }
    }

如果您在每次执行时仅从 CreateAndSave... 方法报告一次,那么您可以使用以下代码:

BackgroundWorker createAndSaveAMatchBGW;
        public Form1()
        {
            InitializeComponent();
            createAndSaveAMatchBGW = new BackgroundWorker();
            createAndSaveAMatchBGW.DoWork += new DoWorkEventHandler(createAndSaveAMatchBGW_DoWork);
            createAndSaveAMatchBGW.RunWorkerCompleted += new RunWorkerCompletedEventHandler(createAndSaveAMatchBGW_RunWorkerCompleted);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            createAndSaveAMatchBGW.RunWorkerAsync(DateTime.Now);
        }

        void createAndSaveAMatchBGW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            label1.Text = ((DateTime)e.Result).ToString();
        }

        void createAndSaveAMatchBGW_DoWork(object sender, DoWorkEventArgs e)
        {
            DateTime dt = (DateTime) e.Argument;
            //you do something with your DateTime
            dt = dt.AddDays(10);
            e.Result = dt;
        }
于 2012-10-28T21:40:24.627 回答
1

实现这种事情的最简单方法是使用 BackgroundWorker。

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

BackgroundWorker 自动处理线程编组并提供允许您更新 UI 的事件。事件处理程序在 UI 线程上运行。

您在 Task1 中所做的事情可以移动到 BackgroundWorker 中,并且您建议在 Task2 中执行的 UI 更新实际上可以响应来自 BackgroundWorker 的进度事件。

ProgressChangedEventArgs提供了可以保存当前单词的用户定义数据。

但是,如果您打算显示您加载的每个单词,Winforms(实际上几乎所有 UI)将无法跟上单独的 CPU 线程仅从文件中加载单词。

于 2012-10-28T20:14:02.637 回答
0

Task1可以在单独的线程上启动。

Task2除非执行一些复杂的逻辑来更新 TextBox,否则您实际上不需要 a 。你真正需要做的是使用TextBox.Invoke()Task1.

于 2012-10-28T20:13:01.077 回答