Ошибка system invalidoperationexception

General I'm trying to write a very simple TCPIP client server in C# to connect to an IP Address, with a port number, and ask quite simple line commands, and then place the replies in a Gridbox,

General

I’m trying to write a very simple TCPIP client server in C# to connect to an IP Address, with a port number, and ask quite simple line commands, and then place the replies in a Gridbox, graph or other display option.

I have looked online and found a down loadable utility that does just this, written by Jayan Nair, and this appears to send the message correctly, and receive the reply ok.

The problem comes when I try and load the reply data into a richtext or GridView.

The error message I’m getting is :-
System.InvalidOperationException

I have asked Microsoft Forums, and they have given me a very complicated, ambiguous and overly involved indication as to what I should do, and this involves something called INVOKE and BeginInvoke, and they whole things seems to be a project in it;s own right.

What I’m after is just an example that works, without being too complicated.

Here’s the code :-

        try
        {
            SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
            int iRx = theSockId.thisSocket.EndReceive(asyn);
            char[] chars = new char[iRx + 1];
            System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
            int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
            // 
            System.String szData = new System.String(chars);
            richTextRxMessage.Text =  szData;  // fails
            //textBox1.Text = szData;          // also fails
            WaitForData();
        }

and here’s the error message :-

base {System.Windows.Forms.TextBoxBase} = {Text = '((System.Windows.Forms.RichTextBox)    (((System.Windows.Forms.RichTextBox)(richTextRxMessage)))).Text' threw an exception of type   'System.InvalidOperationException'}

Additional information is :-
szData contains about 6300 characters, including tabs (9) and returns (13), and is consistant with the message sent from the server
I’ve also tried it with using a textbox instead of richtext, same result

For those interested

Here’s the Microsoft link

http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/12a67fb0-847e-4e2b-baa8-ef6ceed60aa4/


  • Here is just 2 of the code amendments that I’ve tried, both fail on the same error condition
  • I think what I need to do is start C# at a much lower level and not just jump in and hope for the best

       public void OnDataReceived(IAsyncResult asyn)
        {
    
            int InputRx;
            int charLen;
            char[] Inputchars;
            System.Text.Decoder InputDecode;
            System.String szData;
            bool IfInvokeRequired;
    
            try
    
            {
    
                SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
                InputRx = theSockId.thisSocket.EndReceive(asyn);                    // get size of input array
                Inputchars = new char[InputRx + 1];                                   // put i char array
                InputDecode = System.Text.Encoding.UTF8.GetDecoder();
                charLen = InputDecode.GetChars(theSockId.dataBuffer, 0, InputRx, Inputchars, 0);
                szData = new System.String(Inputchars);
                IfInvokeRequired = richTextRxMessage.InvokeRequired;
                if (IfInvokeRequired == true)
                {
                    richTextRxMessage.Invoke((MethodInvoker)delegate { this.Text = szData; });// fails
                    richTextRxMessage.BeginInvoke(new MethodInvoker(() => richTextRxMessage.Text = szData));//fails as well
                }
    
  • Решение проблемы с ошибкой «System.InvalidOperationException: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления ‘имя_элемента_GUI’ не из того потока, в котором он был создан.» заключается в создании и вызове методов-делегатов. Статья написана на основе перевода статьи Rüdiger Klaehn, оригинал см. в [1].

    Проблема обычно возникает, когда необходимо получить доступ на запись к одному и тому же ресурсу асинхронно из нескольких потоков. Например, Вы имеете на форме ListBox, в который задумали выводить сообщения из обработчика события, который обрабатывается в другом потоке. У меня такое произошло, когда понадобилось отображение данных в ListBox, принятых в обработчике события поступления данных по USB.

    MultiThreadingIssue01.png

    Почему такая проблема возникает: ListBox создается в основном потоке (thread), запускающем GUI окна программы и обрабатывающим сообщения главного окна формы. Другие потоки могут быть созданы для поддержки обмена данными с внешними устройствами (сеть Ethernet, COM-порт, USB и т. п.). Эти другие потоки могут обрабатывать события приема данных асинхронно с выполнением основного потока. Поэтому попытка разными потоками что-то записать в ListBox может привести к конфликту с записью в ListBox данных из основного потока GUI интерфейса программы.

    Как проблему можно решить: для ListBox создаются подпрограммы (методы), через которые выводятся данные в ListBox. Данные выводятся в ListBox только через эти подпрограммы, больше никак. Эти подпрограммы делаются защищенными (thread-safe) для вызова из любых потоков через delegate, InvokeRequired, Invoke.

    [Введение]

    Программирование интерфейса пользователя через Windows Forms довольно простое, пока вы не используете несколько потоков. Однако всякий раз, когда Вашему приложению нужно выполнить какую-нибудь фактическую работу, становится необходимым использовать поточную обработку (threading), т. е. создать дополнительный поток (thread) или потоки, чтобы обеспечить работоспособность пользовательского интерфейса (скорость отклика UI). В этом случае программирование Windows Forms может стать довольно сложным.

    [Описание проблемы]

    Вы наверное уже знаете, что Windows Forms главным образом не являются потокозащищенными (not thread safe). Например, Вы не можете безопасно прочитать (get) или установить (set) свойство объекта управления (control) Windows.Forms из любого потока, за исключением того потока, который обрабатывает очередь сообщений формы (message queue). Это чрезвычайно важно, когда Вы делаете модификацию своих элементов управления (controls) Ваших Windows Forms из потока очереди сообщений. Могут быть и другие случаи, когда разные потоки вступают в конфликт при доступе к одному и тому же общему ресурсу – например, обработчик события получения данных от внешнего устройства (USB, сокет Ethernet и проч.) должен выводить данные в ListBox, который был создан в главном окне программы. В этом случае выполнение программы может вызывать исключение «System.InvalidOperationException: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления ‘имя_экземпляра_ListBox’ не из того потока, в котором он был создан.».

    [Стандартное решение]

    Само собой, имеется стандартный механизм для решения этой проблемы. Каждый элемент управления (control) Windows Forms имеет свойство InvokeRequired, которое вернет false, если текущий поток является «родным» для контрола, т. е. является потоком очереди сообщений. Также имеется метод Invoke, который делает возможным поставить выполнение делегата (delegate) с параметрами в очередь сообщений управления.

    Поскольку делегат выполняется непосредственно из очереди сообщений, то не возникает проблемы с потоками. Однако такой стиль программирования может быть довольно утомительным. Чтобы сделать что-то столь же простое, как установка свойства текста или запрет/разрешение элемента управления, Вам нужно определить отдельный метод, который соответствует делегату.

    [Пример: случайные строки (Random Strings)]

    Чтобы проиллюстрировать этот метод, я написал маленькую программу на Windows Forms, которая генерирует случайные строки. Вот кусок кода, который показывает, как сделана синхронизация между рабочим потоком (worker thread) и потоком цикла очереди сообщений (message loop thread). 

    char PickRandomChar(string digits)
    {
        Thread.Sleep(100);
        return digits[random.Next(digits.Length)];
    }
    delegate void SetBoolDelegate(bool parameter);
    void SetInputEnabled(bool enabled)
    {
        if(!InvokeRequired)
        {
            button1.Enabled=enabled;
            comboBoxDigits.Enabled=enabled;
            numericUpDownDigits.Enabled=enabled;
        }
        else
            Invoke(new SetBoolDelegate(SetInputEnabled),new object[] {enabled});
    }
    delegate void SetStringDelegate(string parameter);
    void SetStatus(string status) {
        if(!InvokeRequired)
            labelStatus.Text=status;
        else
            Invoke(new SetStringDelegate(SetStatus),new object[] {status});
    }
    void SetResult(string result) {
        if(!InvokeRequired)
            textBoxResult.Text=result;
        else
            Invoke(new SetStringDelegate(SetResult),new object[] {result});
    }
    delegate int GetIntDelegate();
    int GetNumberOfDigits()
    {
        if(!InvokeRequired)
            return (int)numericUpDownDigits.Value;
        else
            return (int)Invoke(new GetIntDelegate(GetNumberOfDigits),null);
    }
    delegate string GetStringDelegate();
    string GetDigits()
    {
        if(!InvokeRequired)
            return comboBoxDigits.Text;
        else
            return (string)Invoke(new GetStringDelegate(GetDigits),null);
    }
    void Work()
    {
        try
        {
            SetInputEnabled(false);
            SetStatus("Working");        
            int n=GetNumberOfDigits();
            string digits=GetDigits();
            StringBuilder text=new StringBuilder();
            for(int i=0;i!=n;i++)
            {
                text.Append(PickRandomChar(digits));
                SetResult(text.ToString());
            }
            SetStatus("Ready");
        }
        catch(ThreadAbortException)
        {
            SetResult("");
            SetStatus("Error");
        }
        finally
        {
            SetInputEnabled(true);
        }
    }
    void Start()
    {
        Stop();
        thread=new Thread(new ThreadStart(Work));
        thread.Start();
    }
    void Stop()
    {
        if(thread!=null)
        {
            thread.Abort();
            thread=null;
        }
    }

    Здесь используется Thread.Abort, так как это самое простое решение. Если Вы делаете что-то, что не должно быть прервано ни при каких обстоятельствах, то вместо этого Вы должны использовать флаг сигнализации для потока. Здесь приведен простой, но очень повторяющийся код. Имейте в виду, что Вы всегда должны проверить InvokeRequired, потому что вызов Invoke перед созданием очереди сообщений может привести к ошибке. Скачать исходный код проекта (Visual Studio C# 2010) можно по ссылке [7].

    [Генерирование потокозащищенных оберток (thread-safe wrappers)]

    В предыдущей статье (см. [2]) я показал, как можно автоматически генерировать обертки для классов, чтобы заставить их «неявно» реализовать интерфейс. Тот же метод генерации кода можно расширить, чтобы создать обертки, автоматически обеспечивающие вызов метода в правильном потоке. Я позже подробно опишу, как это работает. В первую очередь рассмотрим, как используется весь механизм. Сначала Вы предоставляете соответствующие свойства в Вашей форме (чекбоксы, листбоксы, и проч.), не заботясь о проблемах с потоками. Это именно то, что Вы хотели бы сделать, если бы совсем не использовали многопоточность. 

    public bool InputEnabled
    {
        set
        {
            button1.Enabled=value;
            comboBoxDigits.Enabled=value;
            numericUpDownDigits.Enabled=value;
        }
    }
    public string Status
    {
        set { labelStatus.Text=value;}
    }
    public int NumberOfDigits
    {
        get { return numericUpDownDigits.Value; }
    }
    public string Digits
    {
        get { return comboBoxDigits.Text; }
    }
    public string Result
    {
        set { textBoxResult.Text=value; }
    }

    Затем определите интерфейс, который содержит все свойства и/или методы, к которым может быть получен доступ из других разных потоков. 

    interface IFormState
    {
        int NumberOfDigits { get; }
        string Digits { get; }
        string Status { set; }
        string Result { set; }
        bool InputEnabled { set; }
    }

    Теперь в методе worker все, что Вы должны сделать – создать thread-safe wrapper и использовать его. Для Вас опущен весь повторяющийся код.

    void Work()
    {
        IFormState state=Wrapper.Create(typeof(IFormState),this);
        try
        {
            state.InputEnabled=false;
            state.Status="Working";
            int n=state.NumberOfDigits;
            string digits=state.Digits;
            StringBuilder text=new StringBuilder();

            for(int i=0;i

            {
                text.Append(PickRandomChar(digits));
                state.Result=text.ToString();
            } 
            state.Status="Ready";
        }
        catch(ThreadAbortException)
        {
            state.Status="Error";
            state.Result="";
        }
        finally
        {
            state.InputEnabled=true;
        }
    }

    [Как это работает]

    Генератор обертки (wrapper generator) использует System.Reflection.Emit для генерации proxy-класса, который содержит все требуемые для интерфейса методы. Это также включает методы доступа к свойствам, у которых есть специальная сигнатура.

    Тело этих методов будет делать вызов оригинальных методов напрямую, если InvokeRequired вернул false. Это важно, чтобы удостовериться, что запрос методов также работает, если форма еще не подключена к потоку обработки сообщений.

    Если InvokeRequired вернул true, создается делегат, указывающий на оригинальный метод, и созданный делегат передается в метод Invoke формы. Типы делегата кэшируются так, чтобы Вы не получили несколько типов делегата для той же самой сигнатуры метода.

    Поскольку wrapper generator использует интерфейс для вызова синхронизации ISynchronizeInvoke, Вы можете применить это решение и для приложений, не использующих Windows-Forms. Все, что нужно сделать – самостоятельно реализовать интерфейс и возможно обработку очереди сообщений.

    [Ограничения и возможные проблемы]

    Важно понимать, что пока thread-safe wrapper скрывает издержки потоковой синхронизации, из него нельзя делать выход. К примеру, доступ к свойству через thread safe wrapper будет намного медленнее, чем прямой доступ к свойству, если InvokeRequired вернул true. Поэтому если Вам нужно делать многочисленные сложные изменения в Вашей форме из разных потоков, лучшим решением будет создать один отдельный метод для всех действий и вызывать его, вместо того чтобы использовать отдельные вызовы доступа к свойствам.

    Также нужно иметь в виду, что не каждый объект может быть безопасно передан из одного потока в другой без синхронизации. В общем случае можно безопасно передавать только типы наподобие int, DateTime и т. п. и иммунные ссылочные типы наподобие string. Будьте особенно осторожны при передаче мутированных ссылочных типов (mutable reference types) наподобие StringBuilder из одного потока к другому. Это будет удачным только в том случае, если будет реально обеспечено, что объект не был модифицирован, пока имеется ссылка на этот объект в других потоках, или все будет удачно если объект является thread safe. Если есть сомнения, то просто передайте глубокую копию вместо ссылки.

    [Whidbey]

    Whidbey уменьшает проблемы многопоточности, так как он имеет дополнительную поддержку (см. [5]) для фоновой обработки в Windows Forms, и это тем более делает работу с делегатами намного проще благодаря поддержке анонимных методов (см. [4]), которые являются реально закрытыми (closure, см. [6]).

    Установка свойства в Whidbey намного проще: 

    Invoke(delegate { labelStatus.Text="Working"; });

    Точно так же просто получить значение свойства: 

    int n=(int)Invoke(delegate { return numericUpDownDigits.Value; });

    К сожалению, Whidbey наверное выйдет в релиз одновременно с Duke Nukem Forever, где-нибудь в 2025 году.

    [Ссылки]

    1. Оригинал статьи Rüdiger Klaehn «Making Windows Forms thread safe».
    2. Оригинальная статья о «неявных» интерфейсах «Autocaster — Implicit interfaces for .NET».
    3. Статья о проблемах с потоками в Windows Forms «How to: Make Thread-Safe Calls to Windows Forms Controls «. Русская версия той же статьи.
    4. Отличная статья об анонимных методах (anonymous methods) в системе Whidbey.
    5. Статья о классе BackgroundWorker «A tryst with Whidbey: Background operations in Windows Forms».
    6. Closure (computer science).
    7. Демо-проект ThreadSafeWrapper (Visual Studio C# 2010).

    General

    I’m trying to write a very simple TCPIP client server in C# to connect to an IP Address, with a port number, and ask quite simple line commands, and then place the replies in a Gridbox, graph or other display option.

    I have looked online and found a down loadable utility that does just this, written by Jayan Nair, and this appears to send the message correctly, and receive the reply ok.

    The problem comes when I try and load the reply data into a richtext or GridView.

    The error message I’m getting is :-
    System.InvalidOperationException

    I have asked Microsoft Forums, and they have given me a very complicated, ambiguous and overly involved indication as to what I should do, and this involves something called INVOKE and BeginInvoke, and they whole things seems to be a project in it;s own right.

    What I’m after is just an example that works, without being too complicated.

    Here’s the code :-

            try
            {
                SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
                int iRx = theSockId.thisSocket.EndReceive(asyn);
                char[] chars = new char[iRx + 1];
                System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
                int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
                // 
                System.String szData = new System.String(chars);
                richTextRxMessage.Text =  szData;  // fails
                //textBox1.Text = szData;          // also fails
                WaitForData();
            }
    

    and here’s the error message :-

    base {System.Windows.Forms.TextBoxBase} = {Text = '((System.Windows.Forms.RichTextBox)    (((System.Windows.Forms.RichTextBox)(richTextRxMessage)))).Text' threw an exception of type   'System.InvalidOperationException'}
    

    Additional information is :-
    szData contains about 6300 characters, including tabs (9) and returns (13), and is consistant with the message sent from the server
    I’ve also tried it with using a textbox instead of richtext, same result

    For those interested

    Here’s the Microsoft link

    http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/12a67fb0-847e-4e2b-baa8-ef6ceed60aa4/


  • Here is just 2 of the code amendments that I’ve tried, both fail on the same error condition
  • I think what I need to do is start C# at a much lower level and not just jump in and hope for the best

       public void OnDataReceived(IAsyncResult asyn)
        {
    
            int InputRx;
            int charLen;
            char[] Inputchars;
            System.Text.Decoder InputDecode;
            System.String szData;
            bool IfInvokeRequired;
    
            try
    
            {
    
                SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
                InputRx = theSockId.thisSocket.EndReceive(asyn);                    // get size of input array
                Inputchars = new char[InputRx + 1];                                   // put i char array
                InputDecode = System.Text.Encoding.UTF8.GetDecoder();
                charLen = InputDecode.GetChars(theSockId.dataBuffer, 0, InputRx, Inputchars, 0);
                szData = new System.String(Inputchars);
                IfInvokeRequired = richTextRxMessage.InvokeRequired;
                if (IfInvokeRequired == true)
                {
                    richTextRxMessage.Invoke((MethodInvoker)delegate { this.Text = szData; });// fails
                    richTextRxMessage.BeginInvoke(new MethodInvoker(() => richTextRxMessage.Text = szData));//fails as well
                }
    
  • Как исправить ошибку «System.InvalidOperationException: «Недопустимая попытка чтения при отсутствии данных.»»?

    using (SqlConnection connection = new SqlConnection(@"Data Source=...; Initial Catalog=Airlines; Integrated Security=True"))
    {
        connection.Open();
        string sqlExpression = "SELECT ID FROM Users WHERE ID = 1";
        SqlCommand LoginData = new SqlCommand(sqlExpression, connection);
        SqlDataReader LoginReaderData = LoginData.ExecuteReader();
    
        if (LoginReaderData.HasRows)
        {
            object ID = LoginReaderData["ID"];
    
            Mail.Text = (string)ID;
        }
        else
        {
            MessageBox.Show("Пользователь не найден");
        }
    }

    5f324412d14e7659306673.png


    • Вопрос задан

      более двух лет назад

    • 1559 просмотров

    вы неправильно ридер используете.

    SqlDataReader loginReaderData = LoginData.ExecuteReader();
    
     while (loginReaderData.Read())
     {
        var id = loginReaderData["ID"];
        // ...    
      }

    Но судя по примеру — вам вообще не ридер нужен, а нужно https://docs.microsoft.com/en-us/dotnet/api/system…

    string sqlExpression = "SELECT ID FROM Users WHERE ID = 1";
    SqlCommand loginData = new SqlCommand(sqlExpression, connection);
    var id = (string)loginData.ExecuteScalar();
    //...

    Пригласить эксперта

    Ну как минимум попросить reader прочитать [очередную] строку (Read()) и уже тогда добывать из прочитанной строки поля.


    • Показать ещё
      Загружается…

    13 февр. 2023, в 00:57

    10000 руб./за проект

    13 февр. 2023, в 00:32

    10000 руб./за проект

    13 февр. 2023, в 00:12

    20000 руб./за проект

    Минуточку внимания

    Metall_Version

    2146 / 1283 / 516

    Регистрация: 04.03.2014

    Сообщений: 4,092

    1

    02.04.2014, 13:36. Показов 9969. Ответов 14

    Метки нет (Все метки)


    Есть пример из книги Троелсена 5-го издания , (19 глава),
    в котором описывается работа с классом Task. в частности с методом ForEach.

    В теле метода мы из одной папки в другую копируем изображения (переворачивая их на 180).
    а также записываем в заголовок формы какой поток сейчас работает.
    и при запуске на эту строку выбивает исключение :

    C#
    1
    
    this.Text = string.Format("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId);

    «Исключение типа «System.InvalidOperationException» возникло в System.Windows.Forms.dll, но не было обработано в коде пользователя
    Дополнительные сведения: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления ‘MainForm’ не из того потока, в котором он был создан.»

    если закоментить строку обращение к форме то все работает.
    раньше при работе с потоками тоже такое было . когда из другого потока пытался обратится к элементу формы

    Подскажите в чем проблема

    Вложения

    Тип файла: rar DataParallelismWithForEach.rar (13.8 Кб, 8 просмотров)



    0



    Master of Orion

    Эксперт .NET

    6094 / 4950 / 905

    Регистрация: 10.07.2011

    Сообщений: 14,522

    Записей в блоге: 5

    02.04.2014, 13:40

    2

    Metall_Version, по-моему в исключении все написано: доступ к элементам формы разрешается только из главного потока. Можно заставить часть метода потока выполняться в главном потоке с помощью метода Form.Invoke.



    0



    Эксперт .NET

    5462 / 4233 / 1210

    Регистрация: 12.10.2013

    Сообщений: 12,225

    Записей в блоге: 2

    02.04.2014, 13:42

    3

    Да, так и есть, я так думаю это баг. В смысле, баг в книге.
    Сам когда это читал, увидел. Думаю, он там забыл Invoke() упомянуть. Я поставил Invoke() и избавился от этого.



    0



    2146 / 1283 / 516

    Регистрация: 04.03.2014

    Сообщений: 4,092

    02.04.2014, 14:02

     [ТС]

    4

    Psilon, insite2012, а где ставить Invoke() ? не могу допереть. Методу нужен параметр — делегат. нужно создавать делегат , который будет указывать на метод записи в заголовок ?



    0



    Psilon

    Master of Orion

    Эксперт .NET

    6094 / 4950 / 905

    Регистрация: 10.07.2011

    Сообщений: 14,522

    Записей в блоге: 5

    02.04.2014, 14:04

    5

    C#
    1
    2
    
    string text = string.Format("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId);
    Invoke(()=>this.Text = text));



    1



    Metall_Version

    2146 / 1283 / 516

    Регистрация: 04.03.2014

    Сообщений: 4,092

    02.04.2014, 14:06

     [ТС]

    6

    вроде доперло

    C#
    1
    2
    3
    4
    5
    6
    7
    
    MyDelegate dd = new MyDelegate(ProcessFiles);
                this.Invoke(dd);
     
                Task.Factory.StartNew(() =>
                    {
                        ProcessFiles();
                    });



    0



    Master of Orion

    Эксперт .NET

    6094 / 4950 / 905

    Регистрация: 10.07.2011

    Сообщений: 14,522

    Записей в блоге: 5

    02.04.2014, 14:09

    7

    Metall_Version, если все выполнять в главном потоке, то смысла в других потоков нет вообще.



    0



    2146 / 1283 / 516

    Регистрация: 04.03.2014

    Сообщений: 4,092

    02.04.2014, 14:13

     [ТС]

    8

    Psilon, спасибо . как я понял мы сам процесс записи в заголовок формы делаем через инвоке?

    и кстати у меня эта строчка(2) не работает , пишет
    «Невозможно преобразовать «лямбда-выражение» к типу «System.Delegate», поскольку он не является делегатом
    »



    0



    Эксперт .NET

    5462 / 4233 / 1210

    Регистрация: 12.10.2013

    Сообщений: 12,225

    Записей в блоге: 2

    02.04.2014, 14:13

    9

    Psilon, это тренировочное задание из книги. Там смысл простой, запускается поток, и выводится его номер, в заголовок формы, соответственно поток-то другой. И вот там почему-то нет Invoke(), а без него вылетает ошибка. Я сам на эти грабли наступал, но был небольшой опыт работы с потоками, быстро дошло, по названию ошибки.



    0



    2146 / 1283 / 516

    Регистрация: 04.03.2014

    Сообщений: 4,092

    02.04.2014, 14:15

     [ТС]

    10

    Цитата
    Сообщение от Psilon
    Посмотреть сообщение

    если все выполнять в главном потоке, то смысла в других потоков нет вообще.

    да в том примере с делегатом бред вышел. я получается запускал синхронно метод ProcessFiles через инвоке.
    он выполнялся . а потом когда запускал Task это ошибка опять вылазила



    0



    Эксперт .NET

    5462 / 4233 / 1210

    Регистрация: 12.10.2013

    Сообщений: 12,225

    Записей в блоге: 2

    02.04.2014, 14:20

    11

    Metall_Version, в самом методе, который запускается через поток надо прописать обращение к заголовку формы через Invoke(), и все заработает.



    0



    Metall_Version

    2146 / 1283 / 516

    Регистрация: 04.03.2014

    Сообщений: 4,092

    02.04.2014, 14:25

     [ТС]

    12

    C#
    1
    2
    3
    4
    
    Invoke(new Action(() =>
                                {
                                    this.Text = string.Format("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId);
                                }));

    вот так работает .. обязательно создавать новый Action ? или можно любой делегат ? или можно только Action т.к он указывает на методы которые ничего не возвращают и ничего не передают ?

    Добавлено через 40 секунд

    Цитата
    Сообщение от insite2012
    Посмотреть сообщение

    Metall_Version, в самом методе, который запускается через поток надо прописать обращение к заголовку формы через Invoke(), и все заработает.

    можно пример?



    0



    insite2012

    Эксперт .NET

    5462 / 4233 / 1210

    Регистрация: 12.10.2013

    Сообщений: 12,225

    Записей в блоге: 2

    02.04.2014, 14:46

    13

    Metall_Version, там же дальше есть упоминание, что обращение из другого потока к форме невозможно… У меня есть эта книга, и там так написано…

    Добавлено через 3 минуты
    Вот пример, просто один поток, и уже обращение к форме невозможно без Invoke()…

    C#
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading.Tasks;
    using System.Threading;
     
    namespace Metal_Version
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
     
            private void button1_Click(object sender, EventArgs e)
            {
                Thread thr = new Thread(new ThreadStart(Run)); 
                thr.Start();
            }
            private void Run()
            {
                if (this.InvokeRequired)
                {
                    this.Invoke(new Action(() => this.Text = string.Format("{0}",
                                Thread.CurrentThread.ManagedThreadId)));
                }
     
                //Это не работает!!!!
                //this.Text = string.Format("{0}", Thread.CurrentThread.ManagedThreadId);           
            }
        }
    }



    1



    Metall_Version

    2146 / 1283 / 516

    Регистрация: 04.03.2014

    Сообщений: 4,092

    02.04.2014, 15:00

     [ТС]

    14

    insite2012, спасибо понял . с этим методом только так можно работать ?

    C#
    1
    2
    
    this.Invoke(new Action(() => this.Text = string.Format("{0}",
                                Thread.CurrentThread.ManagedThreadId)));

    то есть только создавая Action ?



    0



    Эксперт .NET

    5462 / 4233 / 1210

    Регистрация: 12.10.2013

    Сообщений: 12,225

    Записей в блоге: 2

    02.04.2014, 15:06

    15

    Ну думаю, можно и другие делегаты применять, типа Action<>, Func, Func<>…
    Там же у Action анонимный метод, (), вместо него можно и явно, думаю, создать метод и сослаться на него…
    Я сам так же как и Вы, учусь, стараюсь разобраться, MSDN не плохо помогает, ну и книги, естественно.



    0



    Понравилась статья? Поделить с друзьями:
  • Ошибка syntax error unexpected end of line scilab
  • Ошибка p2770 toyota
  • Ошибка p2763 тойота филдер
  • Ошибка p2757 toyota tundra
  • Ошибка p275500 audi a6