跨线程操作无效并试图找到解决方案

时间:2015-09-04 12:26:50

标签: c#

它执行@RefreshDataGrid()就好了但是当我尝试执行findCommand()时它给了我这个例外:

  

抛出异常:System.Windows.Forms.dll中的“System.InvalidOperationException”   跨线程操作无效:控制'dgvMySqlKBer'从其创建的线程以外的线程访问。

如果您需要更多信息,请随时询问,无论如何这里是代码。 我发现它与this.Load += Form1_Load;

有关
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using Discord;
using System.Media;
using System.Text.RegularExpressions;
using System.Data;
using System.ComponentModel;
using MySql.Data.MySqlClient;
using System.Linq;

namespace DiscordSongRequest
{
    public partial class Form1 : Form
    {
        string ipaddress = "localhost";
        string username = "root";
        string password = "";

        private DiscordClient client;
        SoundPlayer player = new SoundPlayer();
        Random random = new Random();
        public static readonly Regex YoutubeVideoRegex = new Regex(@"youtu(?:\.be|be\.com)/(?:.*v(?:/|=)|(?:.*/)?)([a-zA-Z0-9-_]+)", RegexOptions.IgnoreCase);

        public Form1()
        {
            this.Load += Form1_Load;
        }

        private void Form1_Load(object sender, System.EventArgs e)
        {
            Task.Factory.StartNew(() => ConnectClient());
            InitializeComponent();            
            dgvMySqlKBer.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            RefreshDataGrid();
        }

        private void RefreshDataGrid()
        {
            try
            {
                string MyConnection = "datasource=" + ipaddress + ";username=" + username + ";password=" + password + "";
                string Query = "select * from discordsongrequest.commands;";
                MySqlConnection MyConn = new MySqlConnection(MyConnection);
                MySqlCommand MyCommand = new MySqlCommand(Query, MyConn);
                MyConn.Open();
                MySqlDataAdapter MyAdapter = new MySqlDataAdapter();
                MyAdapter.SelectCommand = MyCommand;
                DataTable dTable = new DataTable();
                MyAdapter.Fill(dTable);
                dgvMySqlKBer.DataSource = dTable;            
                MyConn.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private async Task ConnectClient()
        {
            try
            {
                client = new DiscordClient();
                client.MessageCreated += async (s, e) =>
                {
                    switch (e.Message.Text)
                    {
                        case "!stop":
                            webBrowser1.Navigate("about:blank");
                            break;
                        case "!hallo":
                            findCommand(e.Message.Text);
                            player.Play();
                            break;                        
                        case "!play":
                            break;
                        case "!random":
                            int randomNumber = random.Next(0, 1000);
                            await client.SendMessage(e.Message.Channel, "Random! You roll a: " + Convert.ToString(randomNumber) + ".");
                            break;
                        case "!coin":
                            randomNumber = random.Next(0, 2);
                            if (randomNumber == 0)
                            {
                                await client.SendMessage(e.Message.Channel, "Coinflip! it lands on: Heads.");
                            }
                            else
                            {
                                await client.SendMessage(e.Message.Channel, "Coinflip! it lands on: Tails.");
                            }
                            break;
                        default:
                            if (e.Message.Text.StartsWith("!play"))
                            {
                                string l = e.Message.Text;
                                l = (l.StartsWith("!play")) ? l.Substring(6) : l;
                                checkForLink(l);
                            }
                            break;
                    }
                };
                await client.Connect("username", "password");
                await client.AcceptInvite("invitecode");
            }

            catch
            {
            }
        }

        private void checkForLink(string l)
        {
            try
            {
                Match youtubeMatch = YoutubeVideoRegex.Match(l);
                if (youtubeMatch.Success)
                {
                    Uri uri = new Uri(l);
                    webBrowser1.Url = uri;
                }
            }

            catch
            {
            }
        }

        private void findCommand(string command)
        {            
            string MyConnection = "datasource=" + ipaddress + ";username=" + username + ";password=" + password + "";
            string Query = "select * from discordsongrequest.commands where command = '" + command + "';";
            MySqlConnection MyConn = new MySqlConnection(MyConnection);
            MySqlCommand MyCommand = new MySqlCommand(Query, MyConn);
            MyConn.Open();
            MySqlDataAdapter MyAdapter = new MySqlDataAdapter();
            MyAdapter.SelectCommand = MyCommand;
            DataTable dTable = new DataTable();
            MyAdapter.Fill(dTable);
            dgvMySqlKBer.DataSource = dTable;
            MyConn.Close();
        }

    }
}

1 个答案:

答案 0 :(得分:-2)

看看这里:How to: Manipulate Controls from Threads

dgvMySqlKBer对象是在主事件线程中创建的,并且您尝试从另一个不是有效操作的线程中访问它。您需要在该对象中调用invoke并将其传递给Action。

    private void findCommand(string command)
    {            
        string MyConnection = "datasource=" + ipaddress + ";username=" + username + ";password=" + password + "";
        string Query = "select * from discordsongrequest.commands where command = '" + command + "';";
        MySqlConnection MyConn = new MySqlConnection(MyConnection);
        MySqlCommand MyCommand = new MySqlCommand(Query, MyConn);
        MyConn.Open();
        MySqlDataAdapter MyAdapter = new MySqlDataAdapter();
        MyAdapter.SelectCommand = MyCommand;
        DataTable dTable = new DataTable();
        MyAdapter.Fill(dTable);

        dgvMySqlKBer.Invoke((MethodInvoker)delegate
        {
            dgvMySqlKBer.DataSource = dTable;
        });         

        dgvMySqlKBer.DataSource = dTable;
        MyConn.Close();
    }