1

Тема: Помилка при запуску WinForms

Хай. От час від часу зустрічкаю таке повідомлення при намаганні запустити проект WinForms

Невозможно вызвать Invoke или BeginInvoke для элемента управления до завершения создания дескриптора окна.

http://не-дійсний-домен/990ec/f794c7d394.png
Як таке може бути, що якийсь метод починає працювати до того, як вікно створилось?

2

Re: Помилка при запуску WinForms

Все дуже просто... Ви намагаєтесь визвати Invoke до того, як буде створене ваше вікно. Знайдіть місце в коді, де зможете розмістити Invoke, щоб його визов був після створення вікна, для елементів якого чи для якого ви робите визов метода Invoke...

3

Re: Помилка при запуску WinForms

lesha.ievenko написав:

Все дуже просто... Ви намагаєтесь визвати Invoke до того, як буде створене ваше вікно. Знайдіть місце в коді, де зможете розмістити Invoke, щоб його визов був після створення вікна, для елементів якого чи для якого ви робите визов метода Invoke...

Ну так, а як мені зрозуміти, коли вікно вже готове?

4 Востаннє редагувалося lesha.ievenko (01.06.2014 16:14:21)

Re: Помилка при запуску WinForms

Вікно в WinForms готове після ініціалізаціїї в конструкторі InitializeComponent(). До цього ви навіть this для нього не зможете виконати... Гляньте також чи не знищується ваша форма до того як ви намагаєтеся визвати метод Invoke. Очевидно, що ви намагаєтеся викликати Invoke, не існуючої форми — вона або не встигла створитися, або  була знищена, або елемент для якого ви викликаєте цей метод не створений ще, або він був знищений...(маю на увазі контрол для якого ви викликаєте Invoke) Думаю так...

5

Re: Помилка при запуску WinForms

lesha.ievenko написав:

Вікно в WinForms готове після ініціалізаціїї в конструкторі InitializeComponent(). До цього ви навіть this для нього не зможете виконати... Гляньте також чи не знищується ваша форма до того як ви намагаєтеся визвати метод Invoke. Очевидно, що ви намагаєтеся викликати Invoke, не існуючої форми — вона або не встигла створитися, або  була знищена, або елемент для якого ви викликаєте цей метод не створений ще, або він був знищений...(маю на увазі контрол для якого ви викликаєте Invoke) Думаю так...

так в мене звертання до компоненту йде після ініціалізації форми...
от конструктор

public Form1()
        {
            InitializeComponent();
            statusLabel.ForeColor = Color.Red;
            statusLabel.Text = "Stoped.";
            Thread.Sleep(2000);
            btnStart_Click(this,new EventArgs());
        }

В btnStart_Click я створюю новий клас. Потім виклакаю метод цього класу, котрий викликає ще один метод, а цей метод викликає ще один метод, і в цьому методі вже йде звертання до компонента форми.
http://не-дійсний-домен/9atKv/e30b312c92.jpg

6

Re: Помилка при запуску WinForms

Ви використовуєте якийсь інший потік чи ні? Якщо цей окремий потік є, то він починає свою роботу з метода SystemMess(). Якщо я правильно вас зрозумів... Так чи ні?

7

Re: Помилка при запуску WinForms

lesha.ievenko написав:

Ви використовуєте якийсь інший потік чи ні? Якщо цей окремий потік є, то він починає свою роботу з метода SystemMess(). Якщо я правильно вас зрозумів... Так чи ні?

Дивіться. Запускаю програму. Після виконання ініціалізації форми (як я думаю), я викликаю метод, котрий знаходиться в класі цієї ж форми, тобто в класі Form1. Далі, в цьому методі я створюю клас Server, та викликаю його метод Server.Start(). Server.Start() викликає метод Server.LoadMap(), а вже в кінці виконання методу Server.LoadMap() викликається метод Server.SystemMessage(), в котрому йде звертання до компоненту форми.

8

Re: Помилка при запуску WinForms

Продемонструйте будь ласка ваш код, а то якось важко приймати рішення відносно нього, не бачивши його.

9

Re: Помилка при запуску WinForms

lesha.ievenko написав:

Продемонструйте будь ласка ваш код, а то якось важко приймати рішення відносно нього, не бачивши його.

весь? там його багацько

10

Re: Помилка при запуску WinForms

Прихований текст
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using GameServer;

namespace SCdll
{
    public partial class Form1 : Form
    {
        private Server server;

        public Form1()
        {
            InitializeComponent();
            statusLabel.ForeColor = Color.Red;
            statusLabel.Text = "Stoped.";
            Thread.Sleep(2000);
            btnStart_Click(this,new EventArgs());
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            if (server == null || !server.IsRunning)
            {
                rtbSystemMessage.Clear();
                server = new Server(int.Parse(tbPort.Text),int.Parse(tbUDPport.Text),this);
                server.Start();
                statusLabel.Text = "Running...";
                statusLabel.ForeColor = Color.GreenYellow;
            }
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            if (server.IsRunning)
            {
                server.Stop();
                statusLabel.ForeColor = Color.Red;
                statusLabel.Text = "Stoped.";
            }
        }

        private void btnCheckClienCount_Click(object sender, EventArgs e)
        {
            server.checkClientCount();
        }

        private void tbPort_TextChanged(object sender, EventArgs e)
        {

        }

        private void dasdasdaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2(this);
            form2.Show();
        }

        public void CreateMob(List<int[]> coors)
        {
            
        }
    }
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq.Expressions;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using MySql.Data.MySqlClient;
using ProtoBuf;
using SCdll;
using SCdll.GServer;
using SCdll.NSClient;
using SCdll.NSClient.ClientInterface;
using SCdll.NSServer;
using SCdll.NSServer.ServerInterface;
using Sdll;

namespace GameServer
{
    public class Server
    {
        private delegate void Del();

        private delegate void DelError(string s);

        private MyTimer timer;
        private int _port;
        private int _UDPport;
        private Socket _socket;
        private Socket _UDPsocket;
        private MySqlConnection _mySqlConnection;
        private string _db_connect;
        private List<Client> clients;
        private Form1 form;
        private bool serverStatus;
        private int lineCount;
        private byte[] UDPbuffer;
        private UdpClient UdpServer;
        private ushort[,] map;

        public bool IsRunning
        {
            get { return serverStatus; }
            set { serverStatus = value; }
        }

        public Server(int port, int UDPport, Form1 form)
        {
            lineCount = 1;
            serverStatus = false;
            _port = port;
            _UDPport = UDPport;
            clients = new List<Client>();
            Config.Initialize(new Action<string>(SystemMessage));
            timer = new MyTimer();
            this.form = form;
            UDPbuffer=new byte[1024];
            UdpServer=new UdpClient(_UDPport);
        }

        public void Start()
        {
            LoadMap();
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _UDPsocket = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
            EndPoint _endPoint = new IPEndPoint(IPAddress.Any, _port);
            _socket.Bind(_endPoint);
            _socket.Listen((int)SocketOptionName.MaxConnections);
            _socket.BeginAccept(new AsyncCallback(AcceptCallback), _socket);
            EndPoint _udpEndPoint = new IPEndPoint(IPAddress.Any,_UDPport);
            timer.AddHandler(ShowTimer);
            timer.Interval = 50;
            timer.Start();
            IsRunning = true;
        }

        private void LoadMap()
        {
            byte[] buff = File.ReadAllBytes(Directory.GetCurrentDirectory() + "\\map.map");
            map = new ushort[400, 400];
            int count1 = 0;

            ushort[] map1 = new ushort[160000];
            for (int i = 0; i < buff.Length; i += 2)
            {
                map1[i / 2] = BitConverter.ToUInt16(buff, i);
            }

            for (int i = 0; i < 400; i++)
            {
                for (int j = 0; j < 400; j++)
                {
                    map[i, j] = map1[count1];
                    count1++;
                }
            }
            SystemMessage("Map has been loaded");
        }        

        private void UDPReceiveCallback(IAsyncResult ar)
        {
            UdpClient client = (UdpClient) ar.AsyncState;
            IPEndPoint IPendPoint = new IPEndPoint(IPAddress.Any, 0);
            byte[] data = client.EndReceive(ar, ref IPendPoint);
            SystemMessage("UDP: receive "+data.Length+" bytes");
            byte[] hashByte = new byte[data.Length-sizeof(ushort)];
            Array.Copy(data,sizeof(ushort),hashByte,0,data.Length-sizeof(ushort));
            ushort hash = GetHash(hashByte);
            if (hash == BitConverter.ToUInt16(data, 0))
            {
                SystemMessage("hash is good");
                ushort id = BitConverter.ToUInt16(data, 2);
                Client cl = clients.Find(
                    delegate(Client c)
                    {
                        return c.userId == id;
                    });
                if (cl!=null)
                {
                    cl.IPendPoint = IPendPoint;
                    SystemMessage("client is exist");
                    ushort messageID = BitConverter.ToUInt16(data, 4);
                    if (messageID > cl.messageID)
                    {
                        foreach (var client1 in clients)
                        {
                            if (client1.IPendPoint != null && client1.userId != id)
                            {
                                client1.lastData = data;
                                UdpServer.BeginSend(data,data.Length,client1.IPendPoint,UDPSendCallback,UdpServer);
                                SystemMessage("UDP: sent ");
                            }
                        }
                    }
                }
            }
            else
            {
                SystemMessage("Hash is bad "+hash);
            }
            client.BeginReceive(UDPReceiveCallback, UdpServer);
        }

        private void UDPSendCallback(IAsyncResult ar)
        {
            UdpClient udpClient = (UdpClient) ar.AsyncState;
            int n = udpClient.EndSend(ar);
            SystemMessage("UDP: sent "+n+" bytes");
        }

        static ushort GetHash(byte[] data)
        {
            int lenght = data.Length;
            byte[] buff;
            if (lenght % 2 == 1)
            {
                buff = new byte[lenght + 1];
                Array.Copy(data, buff, lenght);
                buff[lenght] = 0;
            }
            else
            {
                buff = data;
            }

            ushort hash = 0;
            for (int i = 0; i < lenght; i += 2)
            {
                hash ^= (ushort)BitConverter.ToInt16(buff, i);
            }
            return hash;
        }

        public void Stop()
        {
            foreach (var client in clients)
            {
                client.socket.Shutdown(SocketShutdown.Both);
                client.socket.Disconnect(false);
                client.socket.Close();
            }
            clients.Clear();
            _socket.Dispose();
            UdpServer.Close();
            timer.Stop();
            IsRunning = false;
        }

        private void AcceptCallback(IAsyncResult result)
        {
            try
            {
                Socket acceptSocket = (Socket)result.AsyncState;
                Client client = new Client();
                client.socket = (Socket)acceptSocket.EndAccept(result);
                if (!clients.Contains(client))
                {
                    lock (clients)
                    {
                        clients.Add(client);
                    }
                    SystemMessage("New client has been added");
                    client.socket.BeginReceive(client.bufferReceive, 0, client.bufferReceive.Length, SocketFlags.None,
                    new AsyncCallback(ReceiveCallback), client);
                }
                UdpServer.BeginReceive(UDPReceiveCallback, UdpServer);
                _socket.BeginAccept(new AsyncCallback(AcceptCallback), _socket);
            }
            catch (Exception e)
            {
                SystemMessage(e.Message + " | AcceptCallback");
            }
        }

        private void ReceiveCallback(IAsyncResult result)
        {
            try
            {
                Client client = (Client)result.AsyncState;
                int nBytes = client.socket.EndReceive(result);
                SystemMessage("Received: " + nBytes + " bytes");

                if (nBytes > 0)
                {
                    lock (clients)
                    {
                        int fullLength = 0, dataLength = 0;
                        int startIndex = 0;
                        do
                        {
                            dataLength = BitConverter.ToUInt16(client.bufferReceive, startIndex);

                            byte[] arr = new byte[dataLength];
                            Buffer.BlockCopy(client.bufferReceive, startIndex + 2, arr, 0, dataLength);
                            ClientData command = Serializer.Deserialize<ClientData>(new MemoryStream(arr));
                            ServerData result1 = new SuperExecutor(clients, client, timer).Executor(command);

                            switch (result1.SendingMode())
                            {
                                case SelectSending.SendToSelf:
                                    SendToSelf(client, result1);
                                    break;
                                case SelectSending.SendToOthers:
                                    SendToOthers(client, result1);
                                    break;
                                case SelectSending.SendToClient:
                                    SendToClient(result1);
                                    break;
                                case SelectSending.NoSend:
                                    break;
                            }

                            fullLength = dataLength + 2;
                            startIndex += fullLength;

                            SystemMessage("length: " + dataLength + "  full length: " + fullLength + "  start index: " + startIndex);

                        } while (startIndex < nBytes);
                    }
                }

                if (nBytes == 0)
                {
                    client.socket.Close();
                    lock (clients)
                    {
                        clients.Remove(client);
                        SystemMessage("Client has been removed");
                    }
                }
                if (clients.Contains(client))
                    client.socket.BeginReceive(client.bufferReceive, 0, client.bufferReceive.Length, SocketFlags.None,
                        new AsyncCallback(ReceiveCallback), client);
            }
            catch (SocketException e)
            {
                SystemMessage(e.Message + " ErrorCode: " + e.ErrorCode);
            }
            catch (Exception e)
            {
                SystemMessage(e.Message + " | ReceiveCallback");
            }
        }

        public void checkClientCount()
        {
            SystemMessage(clients.Count.ToString());
        }

        private void ShowTimer(object src, ElapsedEventArgs args)
        {
            form.timerTB.BeginInvoke(new Del(() => form.timerTB.Text = timer.CurrentTime.ToString()));
        }

        public void SystemMessage(string message)
        {
            form.rtbSystemMessage.Invoke(new Del(() => form.rtbSystemMessage.AppendText(lineCount + ") " + message + "\n")));
            lineCount++;
        }

        private void SendToSelf(Client client, ServerData data)
        {
            MemoryStream ms = new MemoryStream();
            Serializer.Serialize(ms, data);
            client.bufferSend = ms.ToArray();
            client.socket.Send(client.bufferSend, 0, client.bufferSend.Length, SocketFlags.None);
            SystemMessage("данные отправилися");
        }

        private void SendToOthers(Client client, ServerData data)
        {
            MemoryStream ms = new MemoryStream();
            Serializer.Serialize(ms, data);

            foreach (var client1 in clients)
            {
                if (client1 != client && client1.isInWorld)
                {
                    client1.bufferSend = ms.ToArray();
                    client1.socket.Send(client1.bufferSend, 0, client1.bufferSend.Length, SocketFlags.None);
                }
            }
        }

        private void SendToClient(ServerData data)
        {
            MemoryStream ms = new MemoryStream();
            Serializer.Serialize(ms, data);

            data.client.bufferSend = ms.ToArray();
            data.client.socket.Send(data.client.bufferSend, 0, data.client.bufferSend.Length, SocketFlags.None);
        }

    }
}

11

Re: Помилка при запуску WinForms

Здається, що вже й не так багато кода... Але на перший погляд проблема може виникати в обробнику ShowTimer або в методі SystemMessage. І скоріше за все, що в обробнику ShowTimer проблема, так як ви запускаєте його доволі часто й не можете проконтролювати чи не запускається він в той час, коли форма з її компонентами виявилася вже знищеною. Думаю, що так...

12

Re: Помилка при запуску WinForms

lesha.ievenko написав:

Здається, що вже й не так багато кода... Але на перший погляд проблема може виникати в обробнику ShowTimer або в методі SystemMessage. І скоріше за все, що в обробнику ShowTimer проблема, так як ви запускаєте його доволі часто й не можете проконтролювати чи не запускається він в той час, коли форма з її компонентами виявилася вже знищеною. Думаю, що так...

То в мене просто шрифт такий, що здається, що багацько кода хД І як це він може запускатись, коли форма знищенною є, якщо проблема виникає при запуску програми, а не при завершенні її виконання?

13

Re: Помилка при запуску WinForms

І ще одне, коли виключення вилазіє, то показується, шо воно вилазіє при виклику Invoke, котрий знаходиться в SystemMessage()

"доказ"

http://не-дійсний-домен/9bSYX/decc39cc56.png

14

Re: Помилка при запуску WinForms

А послідовність ходів до виключення не перевіряли, бо ж кажете, що вилітає на самому початку. А також що робить Config.Initialize(), бо бачу ви передаєте SystemMessage до того як передасте посилання на форму у конструкторі Server....

15

Re: Помилка при запуску WinForms

lesha.ievenko написав:

А послідовність ходів до виключення не перевіряли, бо ж кажете, що вилітає на самому початку. А також що робить Config.Initialize(), бо бачу ви передаєте SystemMessage до того як передасте посилання на форму у конструкторі Server....

нічого такого

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SCdll.GServer
{
    public static class Config
    {
        private static string connectionString;
        private static Delegate _messager;

        static Config()
        {
            try
            {
                StreamReader streamReader = new StreamReader(Directory.GetCurrentDirectory().ToString() + "/config");
                connectionString = streamReader.ReadLine();
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }

        public static void Initialize(Delegate messager)
        {
            _messager = messager;
        }

        public static void ShowMessage(string message)
        {
            _messager.DynamicInvoke(message);
        }

        public static string GetConnectionString()
        {
            return connectionString;
        }


    }
}

16

Re: Помилка при запуску WinForms

якщо не викликати Server.LoadMap() в Server.Start(), то цієї помилки немає...

17

Re: Помилка при запуску WinForms

отак зробив, все працює

 public void SystemMessage(string message)
        {

            if (form.rtbSystemMessage.InvokeRequired)
            {
                form.rtbSystemMessage.Invoke(
                    new Del(() => form.rtbSystemMessage.AppendText(lineCount + ") " + message + "\n")));
            }
            else
            {
                form.rtbSystemMessage.AppendText(lineCount + ") " + message + "\n");
            }
            lineCount++;

        }