Застрял winform при запуске 3 процессов / сбоев потоков - PullRequest
0 голосов
/ 30 апреля 2018

Я новичок в темах в форме Windows. Я занимаюсь разработкой приложения для одной формы, которое показывает опцию отправки сообщений вместе с потоковым видео в веб-браузере и графиком пульса с использованием графиков. Я могу успешно запустить эти процессы отдельно в другой форме, но теперь я хочу встроить все в одну форму, но, как только приложение запускается, оно зависает, показывая только подачу видео и курсор не может двигаться в форме. Мне нужен кто-то, чтобы вести меня в потоке. Thankyou

Это моя желаемая форма и код. Пожалуйста помоги.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using System.Diagnostics;

namespace ClientApp
{
    public partial class Form1 : Form
    {
        private string myMessage = "";
        private TcpClient client = new TcpClient();
        private IPEndPoint serverEndPoint = new 
                                            IPEndPoint(IPAddress.Parse("server 
                                            ip"), port1);
        Socket socket = new Socket(AddressFamily.InterNetwork, 
                        SocketType.Stream, ProtocolType.Tcp);


        public Form1()
        {
            InitializeComponent();
            client.Connect(serverEndPoint);
            socket.Connect("server ip", port2);


            //thread for running video stream
            Thread t1 = new Thread(threadURL);
            t1.Start();

        }

        void threadURL()
        {
            string URL = "server ip";
            webBrowser2.Navigate(URL);
        }


        // now the chat part(send message to Rpi)

        private void RtbClientKeyDown(object sender, KeyEventArgs e)
        {

            if (e.KeyData != Keys.Enter || e.KeyData != Keys.Return)
            {
                myMessage += (char)e.KeyValue;
            }
            else
            {

                SendMessage(myMessage);
                myMessage = "";

            }

        }

        private void SendMessage(string msg)
        {
            NetworkStream clientStream = client.GetStream();

            ASCIIEncoding encoder = new ASCIIEncoding();
            byte[] buffer = encoder.GetBytes(msg);

            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();


        }

        //realtime pulse plot part received from socket
        System.Windows.Forms.Timer chartTimer = new 
        System.Windows.Forms.Timer();

        private void InitChart()
        {
            DateTime time = DateTime.Now;
            chartTimer.Interval = 1000;
            chartTimer.Tick += chartTimer_Tick;
            chart1.DoubleClick += chartDemo_DoubleClick;

            Series series = chart1.Series[0];


            chartTimer.Start();

        }

        //socket receiving pulse values from Rpi
        int ReceiveText()
        {

            byte[] buffer = new byte[1024];
            int iRx = socket.Receive(buffer);
            char[] chars = new char[iRx];

            System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
            int charLen = d.GetChars(buffer, 0, iRx, chars, 0);
            string recv = new string(chars);
            int final = Convert.ToInt16(recv);

            return final;

        }


        void chartDemo_DoubleClick(object sender, EventArgs e)
        {
            chart1.ChartAreas[0].AxisX.ScaleView.Size = 5;
            chart1.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = true;
            chart1.ChartAreas[0].AxisX.ScrollBar.Enabled = true;
        }


        private void LivePulseplot()
        {

            Series series = chart1.Series[0];
            chartTimer.Start();

            series.Points.AddXY(DateTime.Now.ToString("hh:mm:ss"), 
                                                      ReceiveText());
            chart1.ChartAreas[0].AxisX.ScaleView.Position = series.Points.Count - 5;

        }


        void chartTimer_Tick(object sender, EventArgs e)
        {

            Thread tP = new Thread(LivePulseplot);
            tP.Start();

        }
    }
}

1 Ответ

0 голосов
/ 30 апреля 2018

Причина, по которой ваша форма зависает, заключается в том, что основной поток (тот, который создал и отображает пользовательский интерфейс) работает все время.

У вас есть несколько возможностей предотвратить это. Один из них - запускать потоки, которые работают в фоновом режиме (хотя это может быть сложно, потому что вам нужно убедиться, что все, что обновляет пользовательский интерфейс, передает эту ответственность потоку пользовательского интерфейса, потому что другим потокам не разрешено изменять что-либо, созданное в основном потоке. ), как вы делаете в своем коде, а другие используют шаблон async / await или, например, BackgroundWorkers.

В вашей реализации есть несколько проблем. В chartTimer_Tick вы начинаете новую тему. Это будет происходить каждый раз, когда срабатывает таймер (то есть каждые 1000 мс). Вы не должны вызывать chartTimer.Start () в LivePulsePlot, так как таймер уже запущен (или вы не нажмете эту функцию). После того как вы вызвали Start () для таймера, он будет продолжать выполнять свою функцию 'Tick' каждые 1000 мс, пока вы не вызовете Stop ().

Кроме того, System.Windows.Forms.Timer выполняет свой метод в потоке пользовательского интерфейса, что приведет к зависанию пользовательского интерфейса во время работы функции. Вы можете использовать другой таймер, например, System.Timers.Timer, если вы хотите запустить что-то в фоновом режиме.

Одна вещь, которую вы должны принять во внимание, когда делаете это в фоновых потоках, это то, что всякий раз, когда вы хотите обновить некоторый элемент экрана, вам нужно будет попросить поток пользовательского интерфейса сделать это для вас (а не фоновый поток). , Подробнее об этом здесь: https://docs.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls

Еще лучший способ сделать это (хотя вам нужно потратить немного больше времени прямо сейчас) - это использовать async / await или BackgroundWorkers, но способ, которым вы начали его реализовывать, тоже может работать, с небольшим усилий.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...