Single event scheduling

I am writing an application that requires updating the status bar while the database is loading. I set the label to "Loading Database ...", then downloaded the database using BackgroundWorker. When the employee finishes work, I set the label "Database is loaded." However, this is done only at startup, and I do not want the label to be visible much longer, and I would like it to clear a few seconds after the employee finishes. I could place the highlighted timer object on my main, but this only action would be its only work, and it seems that a more elegant solution should exist. So I tried lambda:

void dataLoader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    DataLabel.Text = "Database Loaded";
    System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
    timer.Interval = 5000;
    timer.Tick += new EventHandler((o, a) =>
    {
        DataLabel.Text = "";
        (o as System.Windows.Forms.Timer).Enabled = false;
    });
}

Of course, the space timerexpires after the function exits, and the event is Ticknever called.

How can I get a simple one-time event to fire without using global instance timers?

+3
source share
6 answers

. , - , . . , GC , "" . , , , , . , , "" , . , .

void dataLoader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)  
{  
    DataLabel.Text = "Database Loaded";  
    var timer = new System.Windows.Forms.Timer();  
    timer.Interval = 5000;  
    timer.Tick += (o, a) =>  
    {  
        timer.Stop();
        DataLabel.Text = "";
    };
    timer.Start();
}  
+2

, Thread.Sleep(N) .

+2

Timer, , null.

, ThreadPool - .

. Control.Invoke ...

+1

Visual studio , . , , 5 10 . , , - (, ..)

0

, , :

void dataLoader_DoWork(object sender, DoWorkEventArgs e) {
    // Do work normally.

    // Report progress as complete.
    var worker = sender as BackgroundWorker;
    worker.ReportProgress(100);

    Thread.Sleep(5000);
}

void dataLoader_ProgressChanged(object sender, ProgressChangedEventArgs e) {
  if (e.ProgressPercentage == 100) {
    // Set label here
    DataLabel.Text = "Database Loaded";
  }
}

void dataLoader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    DataLabel.Text = "";
}

This might work a little better than running the asynchronous method, since the thread has already been created for the background worker. Will this work better?

0
source

Queue in WorkItem in ThreadPool, Sleep for 5 seconds, and then BeginInvokeupdate behavior. Here is a basic example:

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

namespace CSharpScratch
{
    class Program
    {
        private static void Main()
        {
            var myForm = new MyForm();
            myForm.ShowDialog();
        }
    }

    class MyForm : Form
    {
        private readonly Label _label;

        public MyForm()
        {
            _label = new Label {Text = "Hello", Parent = this};
            Load += FormLoaded;
        }

        public void FormLoaded(object sender, EventArgs args)
        {
            ThreadPool.QueueUserWorkItem(x =>
                {
                    Thread.Sleep(5000);
                    BeginInvoke(new Action(() => _label.Text = "Goodbye"));
                });
        }
    }
}
0
source

Source: https://habr.com/ru/post/1754428/


All Articles