【问题标题】:How do i make an instance for a new from from a backgroundworker do work event?我如何从后台工作人员做一个新的实例做工作事件?
【发布时间】:2014-01-25 21:14:50
【问题描述】:

我有这个代码,我点击 control + m :

void gkh_KeyDown(object sender, KeyEventArgs e)
        {
            if ((e.KeyCode == System.Windows.Forms.Keys.LControlKey) || (e.KeyCode == System.Windows.Forms.Keys.RControlKey))
            {
                controlDown = true;
            }

            if (e.KeyCode == System.Windows.Forms.Keys.M && controlDown)
            {
                backgroundWorker1.RunWorkerAsync();

然后backgroundworker做工作事件:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            if (mf1 == null)
            {
                mf1 = new MagnifierForm(mConfiguration, System.Windows.Forms.Cursor.Position);
                mf1.Show();
            }
        }

我使用了一个断点并将其转到 MagnifierForm 构造函数并在那里执行所有操作,但是当我单击继续时,我从未看到此 MagnifierForm 表单。为什么?

编辑**

我想使用 backgroundworker 来显示新表单的原因是,在我显示新表单的主表单中,我有一个计时器滴答事件,并且由于某种原因,这个计时器只有在它运行时才会运行,从而生成新表单显示在与鼠标光标不同的位置,并且表单正在移动/滑动到鼠标光标所在的位置。 当计时器不工作时,我会显示新表单并准确显示鼠标光标所在的位置。

我不知道为什么这个计时器事件会导致问题,并且计时器没有通过任何方式连接到我要显示的新表单。

这是我在主窗体中的计时器事件:

private void timer2_Tick(object sender, EventArgs e)
        {
            label1.Visible = true;
            if (counter == 200)
            {
                timer2.Enabled = false;//counter = 0;
                return;
            }
            counter += 1;
            distance = (float)counter;
            CloudEnteringAlert.cloudalert(bitmapwithclouds, distance);
            pictureBox1.Invalidate();

现在我发现如果我删除测试行:

CloudEnteringAlert.cloudalert(bitmapwithclouds, distance);

并且计时器工作没有问题。新表格准确显示鼠标光标所在的位置。 这是导致问题的 cloudalert 方法,我不知道为什么:

public static List<PointF> cloudalert(Bitmap bmp, float kilometers)
        {
            AddDistanceToPoints = new List<PointF>();
            Color c1 = Color.White;
            Color c2 = Color.FromArgb(c1.A,
                (int)(c1.R * 1), (int)(c1.G * 1), (int)(c1.B * 1));
            Load();
            float distance = kilometers / (float)1.09;
            clouds = new List<PointF>();
            clouds1 = new List<PointF>();
            file = Path.GetDirectoryName(Application.LocalUserAppDataPath) + "\\Data" + "\\Data.txt";
            OptionsFile setting_file = new OptionsFile(file);
            LoadPoints_X = setting_file.GetListFloatKey("Points Coordinates X");
            LoadPoints_Y = setting_file.GetListFloatKey("Points Coordinates Y");
            for (int i = 0; i < PointsFloat.Count; i++)
            {
                //clouds1.Add(new PointF(LoadPoints_X[i] - distance, LoadPoints_Y[i]));
                AddDistanceToPoints.Add(new PointF(PointsFloat[i].X - distance, PointsFloat[i].Y));
            }
            bmp = FastComparison(bmp, Properties.Resources.clean_radar_image);
            newbitmap = bmp;
            for (int x = 0; x < AddDistanceToPoints.Count; x++)//clouds1.Count; x++)
            {
                if (AddDistanceToPoints[x].X > 0)//clouds1[x].X > 0)
                {
                    //Color color = bmp.GetPixel((int)clouds1[x].X, (int)clouds1[x].Y);
                    Color color = bmp.GetPixel((int)AddDistanceToPoints[x].X, (int)AddDistanceToPoints[x].Y);
                    int dR = (int)color.R;
                    int dG = (int)color.G;
                    int dB = (int)color.B;
                    if (dR == 0 && dG == 0 && dB == 0)
                    {

                    }
                    else
                    {
                        //clouds.Add(new PointF(clouds1[x].X, clouds1[x].Y));
                        clouds.Add(new PointF(AddDistanceToPoints[x].X, AddDistanceToPoints[x].Y));
                        //newbitmap.SetPixel((int)clouds1[x].X, (int)clouds1[x].Y, Color.White);
                        newbitmap.SetPixel((int)AddDistanceToPoints[x].X, (int)AddDistanceToPoints[x].Y, Color.White);

                    }
                }

            }
            //newbitmap.Save(@"d:\test\newbitmap.jpg");
            if (clouds.Count == 0)
            {
                cloudsfound = false;
                cloudsdistance.Text = distance.ToString();
                //clouds = null;
                return clouds
;
            }
            else
            {
                cloudsfound = true;

                for (int i = 0; i < clouds.Count; i++)
                {
                    pointtocolor.Add(clouds[i]);
                    cloudsdistance.Text = distance.ToString();
                }
            }
            return clouds;
        }

在主窗体中,我通过按钮单击显示新窗体,例如:

private void button1_Click(object sender, EventArgs e)
        {
            if (mf1 == null)
            {
                mf1 = new MagnifierForm(mConfiguration, System.Windows.Forms.Cursor.Position);
                mf1.Show();
            }
        }

那么为什么这个计时器滴答事件或更多为什么这个方法 cloudalert 使表单 mf1 在不同的位置显示一秒钟,然后表单滑动/移动到鼠标光标所在的位置。但是当这个方法我删除它或停止计时器并显示新表单时,没有问题表单显示在鼠标光标所在的位置。

我在屏幕上的任何位置显示它的新表单我不会只在主表单上显示它,而是在鼠标光标所在的位置显示它。鼠标可以在任务栏上或屏幕的 0,0 或任何地方,然后我单击 button1 或我有全局键挂钩,所以我制作 Ctrl + M

当计时器使用此方法运行时 cloudalert 表单将显示在某个不同的位置,然后将幻灯片移动到鼠标光标所在的位置。

您可以在此处获取我试图显示它是放大镜的新表格:

http://www.codeproject.com/Articles/18235/Simple-Magnifier

我想要做的不是使用它拥有的放大镜菜单,而是使用我的按钮单击事件或 ctrl + m 键来显示放大镜玻璃窗体。但是我有这个问题。

如果我使用这个放大镜菜单和计时器正在使用该方法,则没有问题。

奇怪的是我的 timer2/method cloudalert 的问题出在哪里。

【问题讨论】:

  • 从 bgw 线程调用 Show() 应该抛出异常...至少在调试模式下。
  • 我想使用后台工作人员并在那里显示表单的原因是,如果我在 ui 表单代码中显示表单,我有一个计时器,我需要运行它,而这个计时器是新的表格显示在屏幕上的某个点/位置,然后移动/滑动到鼠标光标所在的位置。我不知道为什么。我不知道为什么计时器让它发生。但是现在当我使用后台工作者时,即使计时器正在工作,新表单也会显示鼠标光标所在的位置。但是你告诉我不要在 backgroundowrker 中使用这个 ui。那么我还能怎么做呢?
  • 类似的东西,所以当计时器工作时,新表单将显示为它未连接到我显示它的表单,因此计时器不会中断它。
  • 什么定时器类? .NET 至少有 3 个。
  • 计时器来自工具箱中的设计器,您从工具箱中拖动的常规计时器,然后我制作计时器滴答事件。

标签: c# winforms


【解决方案1】:

首先 - 不要使用来自多个线程的 UI。如果你想在worker完成执行时显示一些东西,然后处理RunWorkerCompleted事件(这个处理程序在主线程上运行):

void backgroundWorker1_RunWorkerCompleted(
    object sender, RunWorkerCompletedEventArgs e)
{
    if (mf1 == null)
    {
        mf1 = new MagnifierForm(mConfiguration, Cursor.Position);
        mf1.Show();
    }
}

第二 - 你的代码不工作,因为后台线程退出。如果您将mf1.Show() 更改为mf1.ShowDialog(),那么您将看到您的表单。

【讨论】:

  • Sergey 这个 mf1.ShowDialog() 解决了我的计时器问题。我在上面描述了我在显示新表单的表单中的计时器问题。但是由于在后台工作人员中使用 ui 是一件坏事,我还能做什么?
  • @user3200169 Timer.Tick 事件处理程序将在主线程上执行 - 显示表单应该没有任何问题。也许您连续多次触发事件?
【解决方案2】:

DoWork 在工作线程中运行。您不应该尝试从那里更改您的 UI,而只能从您的主 UI 线程更改。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-18
    相关资源
    最近更新 更多