在运行新表单时获取InvalidOperationException是program.cs

时间:2015-10-21 23:19:00

标签: c# bots twitch

我正在制作一个抽搐的聊天机器人,由于某种原因,我有时会收到错误,说我正在对一个对象进行跨线程调用,但是我找不到任何可能导致这种情况的事情,我尝试过试一试关于application.run语句的声明,但没有解决它

的Program.cs:

    #region variables
    #region itunes variables
    iTunesApp player = new iTunesApp();
    #endregion

    static Irc irc;

    string nickname;
    String message;
    String rawMessage;

    int dVolume = 100;

    string fadeDir = "";
    int fadeSpeed = 2;

    #region banned_words
    String[] bannedWords = { dont want to put these on this website :P};
    #endregion

    Thread Messages;

    Form2 f2;

    WebClient Client = new WebClient();

    List<String> viewers;
    #endregion

    public Form1()
    {
        InitializeComponent();

        player.OnPlayerPlayEvent += new _IiTunesEvents_OnPlayerPlayEventEventHandler(player_OnPlayerPlayingTrackChangedEvent);

        irc = new Irc("irc.twitch.tv", 6667, "ZChembot", "oauth");
        irc.joinRoom("zchem");

        irc.send("Starting up...");
        irc.sendIrc("CAP REQ :twitch.tv/membership");

        Messages = new Thread(new ThreadStart(getMessages));
        Messages.IsBackground = true;
        Messages.Start();

        fade.Enabled = true;

        f2 = new Form2(this);
        f2.Show();

        getNames.Enabled = true;
    }

    public void player_OnPlayerPlayingTrackChangedEvent(object iTrack)
    {
        if (InvokeRequired)
        {
            this.Invoke(new Action<object>(player_OnPlayerPlayingTrackChangedEvent), new object[] { iTrack });
            return;
        }

        IITTrack track = new iTunesApp().CurrentTrack;

        if (String.IsNullOrEmpty(sound))
        {
            song.Text = "Song: " + track.Name;
            StreamWriter file = new StreamWriter(@"c:\users\ben\desktop\twitch\Song.txt");
            file.WriteLine(track.Name);
            file.Close();
            artist.Text = "Artist: " + track.Artist;
            album.Text = "Album: " + track.Album;
        }

        f2.enableTimer();
        f2.update();
    }

    public void Destroy()
    {
        player.OnPlayerPlayEvent -= player_OnPlayerPlayingTrackChangedEvent;

        Marshal.ReleaseComObject(player);
    }

    #region threads
    private void getMessages()
    {
        while (true)
        {
            message = irc.readMessage();
            if (checkBox1.Checked)
            {
                updateChat("$NOTICE", message, Color.Purple);
            }
            rawMessage = message;

            #region PRIVMSG
            if (!String.IsNullOrEmpty(message))
            {
                if (message.Contains("PRIVMSG #zchem"))
                {
                    nickname = rawMessage.Substring(1, message.IndexOf("!") - 1);
                    int start = message.IndexOf("#zchem") + 8;
                    String str = message.Substring(start);
                    message = str;

                    updateChat(nickname, message, Color.Black);
                }
                #endregion

                #region notices
                //successful connection
                if (message.StartsWith(":tmi.twitch.tv 001 zchembot :Welcome, GLHF!"))
                {
                    updateChat("$NOTICE", "successfully connected to the chat", Color.Green);
                }
                //the server pings the bot
                if (message.StartsWith("PING tmi.twitch.tv"))
                {
                    updateChat("$NOTICE", "Recieved a ping from the server", Color.Blue);
                    irc.sendIrc("PONG");
                }
                #endregion

                #region play
                if (message.StartsWith("!play"))
                    player.Play();
                #endregion

                #region volume up
                if (message.StartsWith("!volume up"))
                {
                    if (IsDigitsOnly(message.Substring(message.IndexOf(" ") + 1, message.Length)))
                    {
                        player.SoundVolume += int.Parse(message.Substring(message.IndexOf(" ") + 1, message.Length));
                        irc.send("The music volume has been changed to " + player.SoundVolume + "%");
                    }
                }
                #endregion

                #region volume down
                if (message.StartsWith("!volume down"))
                {
                    if (IsDigitsOnly(message.Substring(message.IndexOf(" ", 10) + 1, message.Length)))
                    {
                        player.SoundVolume -= int.Parse(message.Substring(message.IndexOf(" ") + 1, message.Length));
                        irc.send("The music volume has been changed to " + player.SoundVolume + "%");
                    }
                }
                #endregion

                #region vurrent volume
                if (message.StartsWith("!current volume"))
                {
                    irc.send("The current music volume is at " + player.SoundVolume + "%");
                }
                #endregion

                #region join
                if (rawMessage.EndsWith("JOIN #zchem"))
                {
                    //detects when users join the channel
                    nickname = rawMessage.Substring(1, message.IndexOf("!") - 1);
                    irc.send("Hello, " + nickname + "!");
                }
                #endregion

                #region part
                if (rawMessage.EndsWith("PART #zchem"))
                {
                    nickname = rawMessage.Substring(1, message.IndexOf("!") - 1);
                    irc.send(nickname + "has left the chat");
                    MessageBox.Show(nickname + "has left the chat");
                }
                #endregion
            }

            Thread.Sleep(100);
        }
    }

    public void fade_Tick(object sender, EventArgs e)
    {
        if (this.Visible)
        {
            if (fadeDir.Equals("up"))
            {
                player.Play();
                if (player.SoundVolume + fadeSpeed > dVolume)
                    player.SoundVolume = dVolume;
                else
                    player.SoundVolume += fadeSpeed;
            }
            else if (fadeDir.Equals("down"))
            {
                if (player.SoundVolume - fadeSpeed < 0)
                    player.SoundVolume = 0;
                else
                    player.SoundVolume -= fadeSpeed;
            }
            else if (player.SoundVolume == dVolume || player.SoundVolume == 0)
                fadeDir = "";

            if (player.SoundVolume == 0)
                player.Pause();
        }
    }
    #endregion

    #region itunes events
    private void playpause_Click(object sender, EventArgs e)
    {
        if (playpause.Text.Equals("❚❚"))
        {
            fadeDir = "down";
            playpause.Text = "►";
        }
        else
        {
            fadeDir = "up";
            playpause.Text = "❚❚";
        }
    }

    private void nextSong_Click(object sender, EventArgs e)
    {
        player.NextTrack();
    }

    private void lastSong_Click(object sender, EventArgs e)
    {
        player.PreviousTrack();
    }

    private void showArt_CheckedChanged(object sender, EventArgs e)
    {
        if (showArt.Checked)
        {
            f2.Show();
        }
        else
        {
            f2.Hide();
        }
    }

    private void soundDelay_TextChanged(object sender, EventArgs e)
    {
        if (!IsDigitsOnly(soundDelay.Text))
        {
            soundDelay.Text = "5";
        }
    }
    #endregion

    #region form events
    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        Destroy();
    }
    #endregion

    bool IsDigitsOnly(string str)
    {
        foreach (char c in str)
        {
            if (c < '0' || c > '9')
                return false;
        }
        return true;
    }


    public void updateChat(string nickname, string message, Color color)
    {
        String text;
        String time = DateTime.Now.ToShortTimeString();
        time = time.Substring(0, time.Length - 3);

        if (InvokeRequired)
        {
            this.Invoke(new Action<string, string, Color>(updateChat), new object[] { nickname, message, color });
            return;
        }

        if (nickname.Equals("$NOTICE"))
            nickname = "";
        else
            nickname += ":  ";

        text = ("[" + DateTime.Now.Hour + ":" + DateTime.Now.Minute + "]  " + nickname + message + "\n");

        chat.SelectionStart = chat.TextLength;
        chat.SelectionLength = 0;
        chat.SelectionColor = color;
        chat.AppendText(text);
    }
}

Form1.cs中:

    private string username;
    public TcpClient tcpClient;
    private StreamReader inputStream;
    private StreamWriter outputStream;

    public Irc(string ip, int port, string username, string password)
    {
        this.username = username;

        tcpClient = new TcpClient(ip, port);
        inputStream = new StreamReader(tcpClient.GetStream());
        outputStream = new StreamWriter(tcpClient.GetStream());

        outputStream.WriteLine("PASS " + password);
        outputStream.WriteLine("NICK " + username);
        outputStream.WriteLine("USER " + username + " 8 * :" + username);
        outputStream.Flush();
    }

    public void joinRoom(string channel)
    {
        outputStream.WriteLine("JOIN #" + channel);
        outputStream.Flush();
    }

    public void sendIrc(string message)
    {
        outputStream.WriteLine(message);
        outputStream.Flush();
    }

    public void send(string message)
    {
        //sendIrc(":" + username + "!" + username + "@" + ".tmi.twitch.tv PRIVMSG #zchem :" + message);
    }

    public string readMessage()
    {
        string message = inputStream.ReadLine();
        Console.WriteLine(message);
        return message;
    }
}

Irc.cs:

    Form1 f1;

    public Form2(Form1 f1)
    {
        InitializeComponent();

        this.f1 = f1;

        timer1.Enabled = true;
    }

    public void update()
    {
        IITTrack track = player.CurrentTrack;

        IITArtworkCollection Art1 = track.Artwork;
        IITArtwork Art2 = Art1[1];

        Art2.SaveArtworkToFile(@"c:\users\ben\desktop\twitch\Album.png");
        Stream s = File.Open(@"c:\users\ben\desktop\twitch\Album.png", FileMode.Open);

        Image temp = Image.FromStream(s);

        s.Close();

        this.BackgroundImage = resize(temp);

        if (!f1.Visible)
        {
            System.Environment.Exit(1);
        }
    }

    static public Bitmap Copy(Bitmap srcBitmap, Rectangle section)
    {
        // Create the new bitmap and associated graphics object
        Bitmap bmp = new Bitmap(section.Width, section.Height);
        Graphics g = Graphics.FromImage(bmp);

        // Draw the specified section of the source bitmap to the new one
        g.DrawImage(srcBitmap, 0, 0, section, GraphicsUnit.Pixel);

        // Clean up
        g.Dispose();

        // Return the bitmap
        return bmp;
    }

    public static IEnumerable<Color> GetPixels(Bitmap bitmap)
    {
        for (int x = 0; x < bitmap.Width; x++)
        {
            for (int y = 0; y < bitmap.Height; y++)
            {
                Color pixel = bitmap.GetPixel(x, y);
                yield return pixel;
            }
        }
    }



    #region enable click-through
    public enum GWL
    {
        ExStyle = -20
    }

    public enum WS_EX
    {
        Transparent = 0x20,
        Layered = 0x80000
    }

    public enum LWA
    {
        ColorKey = 0x1,
        Alpha = 0x2
    }

    [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
    public static extern int GetWindowLong(IntPtr hWnd, GWL nIndex);

    [DllImport("user32.dll", EntryPoint = "SetWindowLong")]
    public static extern int SetWindowLong(IntPtr hWnd, GWL nIndex, int dwNewLong);

    [DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]

    public static extern bool SetLayeredWindowAttributes(IntPtr hWnd, int crKey, byte alpha, LWA dwFlags);

    protected void enable()
    {
        int wl = GetWindowLong(this.Handle, GWL.ExStyle);
        wl = wl | 0x80000 | 0x20;
        SetWindowLong(this.Handle, GWL.ExStyle, wl);
        SetLayeredWindowAttributes(this.Handle, 0, 128, LWA.Alpha);
    }

    protected void disable()
    {
        SetWindowLong(this.Handle, GWL.ExStyle, 0);
        SetLayeredWindowAttributes(this.Handle, 0, 128, LWA.Alpha);
    }
    #endregion

    #region image stuph
    public Size GenerateImageDimensions(int currW, int currH, int destW, int destH)
    {
        //double to hold the final multiplier to use when scaling the image
        double multiplier = 0;
        //string for holding layout
        string layout;
        //determine if it's Portrait or Landscape

        if (currH > currW) layout = "portrait";
        else layout = "landscape";

        switch (layout.ToLower())
        {
            case "portrait":
                //calculate multiplier on heights
                if (destH > destW)
                {
                    multiplier = (double)destW / (double)currW;
                }
                else
                {
                    multiplier = (double)destH / (double)currH;
                }
                break;
            case "landscape":
                //calculate multiplier on widths
                if (destH > destW)
                {
                    multiplier = (double)destW / (double)currW;
                }
                else
                {
                    multiplier = (double)destH / (double)currH;
                }
                break;
        }
        //return the new image dimensions
        return new Size((int)(currW * multiplier), (int)(currH * multiplier));
    }

    private Image resize(Image img)
    {
        try
        {
            //calculate the size of the image
            Size imgSize = GenerateImageDimensions(img.Width, img.Height, this.Width, this.Height);

            //create a new Bitmap with the proper dimensions
            Bitmap finalImg = new Bitmap(img, imgSize.Width, imgSize.Height);

            //create a new Graphics object from the image
            Graphics gfx = Graphics.FromImage(img);

            //clean up the image (take care of any image loss from resizing)
            gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;

            //set the new image
            return finalImg;
        }
        catch (System.Exception e)
        {
            MessageBox.Show(e.Message);
            return null;
        }
    }
    #endregion

    private void timer1_Tick(object sender, EventArgs e)
    {
        this.Location = new Point(1920 - this.Width, 1080 - this.Height - 40);
        if (Cursor.Position.X >= this.Location.X && Cursor.Position.X <= this.Location.X + this.Width && Cursor.Position.Y >= this.Location.Y && Cursor.Position.Y <= this.Location.Y + this.Height)
        {
            enable();
        }
        else
        {
            disable();
        }
    }

    private void timer2_Tick(object sender, EventArgs e)
    {
        IITTrack track = player.CurrentTrack;
        double max = track.Duration;
        double val = player.PlayerPosition;
        double prog = (int)(val/max * 100);
        progressBar1.Value = (int)prog;
    }

    public void enableTimer()
    {
        timer2.Enabled = true;
    }
}

}

Form2.cs:

print('hi', 'there')
print 'what', 'now?'
print('nothing')

2 个答案:

答案 0 :(得分:0)

正如调试器所说,你正在进行跨线程调用。

界面只能从主线程更新,您可以从辅助线程更新界面。

您在

上开始一个新主题
Messages = new Thread(new ThreadStart(getMessages));

在getMessages函数中,您正在更新表单,因此这是跨线程调用。

如果您调用对updateChat和MessageBox的调用,我认为您将有足够的,如果没有,则修改getMessages中的其他函数调用也会更新接口。

干杯。

答案 1 :(得分:-1)

在你正在创建线程的构造函数中尝试这个

Form1.CheckForIllegalCrossThreadCalls = false;

在这行InitializeComponent();

之后

注意:这很危险

尝试安全线程调用的委托方法。