winforms 在后台线程上的两个图像之间交替

hujrc8aj  于 2023-03-13  发布在  其他
关注(0)|答案(3)|浏览(177)

我是C#的新手,所以我还在学习很多东西。
在表格上,我尝试将LED的图像从一种颜色更改为另一种颜色,然后更改回来
我希望进程异步运行,这样它就不会阻塞调用它的主线程。到目前为止,没有发生任何更改,我不确定为什么它不工作。
我创建了这样的任务

public async Task ChangeCallLed()
    {
        await Task.Run(() =>
        {
            this.Invoke((MethodInvoker)delegate
            {
                Globals.mForm.sndPageCall_lbl.Image = Resources.led_green_black;
                Globals.mForm.sndPageCall_lbl.Update();
            });
            Thread.Sleep(1000);
            this.Invoke((MethodInvoker)delegate
            {
                Globals.mForm.sndPageCall_lbl.Image = Resources.led_blue_black;
                Globals.mForm.sndPageCall_lbl.Update();
            });
            Thread.Sleep(1000);
            this.Invoke((MethodInvoker)delegate
            {
                Globals.mForm.sndPageCall_lbl.Image = Resources.led_amber_black;
                Globals.mForm.sndPageCall_lbl.Update();
            });
        });
    }

我在主线程中多次调用该任务,如下所示
编辑:全局变量:

static class Globals { 
    public static MainForm mForm; 
    public static PagerCall pCall; 
}

Edit:main方法调用:

static void Main() { 
    ApplicationConfiguration.Initialize(); 
    Globals.mForm = new MainForm(); 
    Globals.pCall = new PagerCall(); 
    //Globals.beepDetected = new BeepDetected(); 
    Application.Run(Globals.mForm); 
}

当主线程完成时,它会 Flink (上面的代码也是这样),我只是不知道我做错了什么。
我试过很多方法,比如让主线程的调用是异步的,但没有改变。我只是想让led看起来 Flink ,而不会阻塞主线程。

mutmk8jj

mutmk8jj1#

对于Windows窗体。我建议您尝试BackgroundWorker。它在UI线程中提供了“ReportProgress”事件更改/更新控件,而不需要额外的代码。
如果要手动创建线程/任务。必须对UI线程执行“调用”以访问其资源。这需要您必须实现和理解的附加代码。示例. Thread-Safe Control

tquggr8v

tquggr8v2#

我建议使用System.Windows.Forms.Timer而不是线程,这样你就不用担心线程的安全性和协调性了,将定时器的Interval设置为1000,并将下面的代码放入Tick事件处理程序中:

private int _sndPageCall_Index = 0;

private void Timer1_Tick(object sender, EventArgs e)
{
    switch (_sndPageCall_Index++ % 3)
    {
        case 0: Globals.mForm.sndPageCall_lbl.Image = Resources.led_green_black; break;
        case 1: Globals.mForm.sndPageCall_lbl.Image = Resources.led_blue_black; break;
        case 2: Globals.mForm.sndPageCall_lbl.Image = Resources.led_amber_black; break;
    }
}

可以使用Enabled属性或Start/Stop方法启动和停止计时器。

zujrkrfu

zujrkrfu3#

你的帖子说你是
尝试将LED的图像从一种颜色改变为另一种颜色睡眠一秒钟,然后变回来。
这里,在一般形式中,是一种在特定时间间隔更新UI元素(例如,改变颜色或图像)而不阻塞UI线程的方法。

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        buttonFlash.Click += onClickFlash;
    }

    private void onClickFlash(object sender, EventArgs e)
    {
        _ = ChangeCalled();
    }        

    private async Task ChangeCalled()
    {
        foreach (var color in new Color[] 
        {
            Color.LightGreen,
            Color.CornflowerBlue,
            Color.Goldenrod,
        })
        {
            led1.BackColor= color;
            await Task.Delay(TimeSpan.FromSeconds(1));
        }
        led1.BackColor = Color.DimGray;
    }
}

其中:

class LED : Label
{
    protected override void OnCreateControl()
    {
        base.OnCreateControl();
        var region = new Region(new Rectangle(Point.Empty, ClientSize));
        Bitmap bitmap = new Bitmap(Width, Height);
        Graphics graphics = Graphics.FromImage(bitmap);
        graphics.FillEllipse(
            Brushes.LimeGreen,
            new RectangleF(
                new PointF(4, 4),
                new SizeF(bitmap.Width - 8, bitmap.Height - 8)));
        for (int x = 0; x < bitmap.Width; x++) for (int y = 0; y < bitmap.Height; y++)
            {
                Color pixel = bitmap.GetPixel(x, y);
                if (pixel.ToArgb() != Color.LimeGreen.ToArgb())
                {
                    region.Exclude(new Rectangle(x, y, 1, 1));
                }
            }
        Region = region;
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        using (var pen = new Pen(Color.White, 2)) 
        {
            e.Graphics.DrawEllipse(
                pen,
                new RectangleF(
                    new PointF(6, 6),
                    new SizeF(Width - 12, Height - 12)));
        }
    }
}

相关问题