Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# PictureBox上的InvokeRequired为true。如何应对?_C#_.net_Winforms_Picturebox_Invokerequired - Fatal编程技术网

C# PictureBox上的InvokeRequired为true。如何应对?

C# PictureBox上的InvokeRequired为true。如何应对?,c#,.net,winforms,picturebox,invokerequired,C#,.net,Winforms,Picturebox,Invokerequired,我的PictureBox上有另一个电话,给了我3种错误,一些很好的答案来自于我。所以,它让我找到了我的问题所在,但现在要解决它,我不是100%确定 基本上,我有一个Windows窗体计时器,它检查某个事件是否为真,如果为真,那么它会告诉系统在所述事件(值)超过某个阈值2秒后发送一些数据 我想我所有的计时器都在用我的PictureBox制造恶劣的比赛条件,我在几个地方使用它来获取图像: new Bitmap(myPicBox.Image); 等等 我在某个地方读到计时器上的间隔至少应该是50。

我的PictureBox上有另一个电话,给了我3种错误,一些很好的答案来自于我。所以,它让我找到了我的问题所在,但现在要解决它,我不是100%确定

基本上,我有一个Windows窗体计时器,它检查某个事件是否为真,如果为真,那么它会告诉系统在所述事件(值)超过某个阈值2秒后发送一些数据

我想我所有的计时器都在用我的PictureBox制造恶劣的比赛条件,我在几个地方使用它来获取图像:

new Bitmap(myPicBox.Image); 
等等

我在某个地方读到计时器上的间隔至少应该是50。从33开始。我发现我可以做一个picCapture.invoker,看看它是否会基本消失。我知道我需要使用一个委托,但我只使用过那些来设置一些东西。。。不从…获取图像。。。。不知道如何设置。。。我知道是什么导致了它,这是代码的组合:

private void timer1_Tick(object sender, EventArgs e)
    {
          if(someCOnditionTrue)
          {

                    TimerCallback tc = new TimerCallback(sendDataFast); //only 
                       //doing all this so i can have the method run two seconds after     
                       // the condition is detected to be true.
                    System.Threading.Timer t = new System.Threading.Timer(tc, null, 2000, Timeout.Infinite);
          }
   }



    void sendDataFast(Object stateObject)
    {

        //using this so the execution is not haulted while the sending of data takes place.
        EmergencyDelegate delEmergency =
                     new EmergencyDelegate(mic.sendEmergencyData);

        Image imgclone;

        if (picCapture.InvokeRequired)
        {                 
            Console.WriteLine("HFS Batman! its going to die ");
        }
        lock (lockObject2) //i admit no clue what im doing here and doesn't seem to help.
        {
            Image img = picCapture.Image;
            imgclone = (Image)img.Clone();
        }
        delEmergency.BeginInvoke(imgclone, null, null); //deep in the call to
        //sendEmergencyData i get the **ParameterNotValid** almost everytime.

        imgclone.Dispose(); //to free memory?


    }
根据我前面的问题,似乎不再在timer1_tick事件中出现内存问题或其他错误。。。(内存不足错误为1)


我认为最大的问题是,当我需要picCapture.invoker的图像数据时,我如何处理它?我敢肯定是计时器内的线程计时器调用导致了这一问题

顾名思义,
invokererequired
意味着在访问控件时需要调用
Invoke
(或
BeginInvoke

请注意,这是/,而不是代理中存在的
调用/BeginInvoke
。。。虽然您需要一个委托才能调用
Invoke
/
BeginInvoke
,但这只是为了让混合更加混乱


有关更多详细信息,请参阅。整个教程可能需要更新,但我相信这一点是可以的。在其他情况下,你可能也想考虑使用,但我不认为这可能与你在这个特定的情况下相关。

< P>我认为你对发票有错误的理解。InvokeRequired表示当前线程与UI线程不同,现在访问控件状态将不安全。如果是这种情况,那么您必须使用
Control.Invoke
来封送对UI线程的调用,然后访问控件状态。阅读更多信息


在您的情况下,除非PictureBox图像正在更改,否则我建议您先复制图像并使用它。否则,您需要使用
控件。Invoke

您有太多的线程来完成此任务。计时器和委托的BeginInvoke()方法都将使用线程池线程。问题是PictureBox.Image属性只是部分线程安全。一次只能由一个线程访问它。当UI线程在代码调用Clone()方法的同一时间绘制图像时,代码将异常终止

您的lock语句无法解决问题,PictureBox正在访问Image属性,而没有使用相同的锁。我强烈建议首先不要使用线程,使用System.Windows.Forms.Timer而不是System.threading.Timer。它的勾号事件在UI线程上引发。然而,这将使UI线程在事件运行时无响应,这取决于用户是否注意到这一点需要多长时间。比如说,超过100毫秒会成为一个问题

唯一的其他方法是尝试使PictureBox控件线程安全。这在某种程度上是可能的。向项目中添加一个新类并粘贴如下所示的代码。编译。将工具箱顶部的新控件放到窗体上,替换现有的PB。请注意,这只是部分解决方案,显示动画GIF或使用ImageLocation属性仍然会引起轰动。使用提供的Clone方法,而不是对Image属性调用Clone

using System;
using System.Drawing;
using System.Windows.Forms;

class MyPictureBox : PictureBox {
    private object locker = new object();
    public new Image Image {
        get { return base.Image; }
        set { lock (locker) { base.Image = value; } }
    }
    public Image Clone() {
        lock (locker) {
            return (this.Image != null) ? (Image)this.Image.Clone() : null;
        }
    }
    protected override void OnPaint(PaintEventArgs pe) {
        lock (locker) {
            base.OnPaint(pe);
        }
    }
}

谢谢,我马上去看看。我以前使用过委托调用方法,但那是我“真正的工作”,我这里没有代码,所以不确定我在那里做了什么。。。有一段时间了。@Jon:关于的示例,是否真的需要对“stopping”变量使用锁?它似乎只能通过Stop()调用进行设置,而且永远不能取消设置。只是问一下,因为我使用了一个非常类似的类,但我并没有锁定我的停止变量的等价物。@something更好:要么需要它是易失性的,要么需要锁定。否则就不能保证一个线程中的设置会在另一个线程中被看到。好吧,我喜欢这个样子,让我感觉更温暖和模糊。我看到线程太多的问题,我没有办法解决。我使用的计时器(至少是主计时器)是windows窗体计时器。其他的是线程计时器和代理。我试图做的事情听起来很简单,但显然在幕后发生的事情远比想象的要多。我想我可以在我的表单上使用这个新控件,并且仍然可以通过图像属性访问图像?是的,这就是我的意图。试试看。