Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> многопоточное клиент-серверное приложение, Работа с потоками 
:(
    Опции темы
AGENTxXx
Дата 8.6.2009, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 231
Регистрация: 8.6.2009

Репутация: нет
Всего: 1



Есть клиентская и серверная часть. Нужно чтобы когда клиент цеплялся к серверу чтобы у сервера в listbox или в richtextbox записывалось: клиент подключился/клиент отключился. Проблема в том что поток в просто "не видет" на самом деле эти элементы. Если говорить яснее то он может к ним обратиться и выполнять все операции, но не может физически изменить. Как я понимаю это происходит по тому что они принадлежат другому потоку. Я что то не могу понять как это реализовать.... Если есть знатоки в этой теме, помогите!
Вот текст серверной части. Я думаю что клиентская тут не понадобится
Код

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.IO;
using System.Net;
using System.Net.Sockets;
using System.Data.SqlClient;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;

namespace t1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();            
        }

        static private SqlConnection con =
            new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Documents and Settings\Администратор\Мои документы\серверное приложение\t1\t1\students.mdf;Integrated Security=True;User Instance=True");
      
        static string otpr = null;
        static Form1 rt = new Form1();
        static String data = null;
        static List<string> pr = new List<string>();
        static public DataSet GetStudents()
        {
            SqlCommand com = con.CreateCommand();
            com.CommandText = "SELECT id, name Имя, surname Фамилия FROM students";
            DataSet ds = new DataSet();
            SqlDataAdapter adapter = new SqlDataAdapter(com);
            con.Open();
            try
            {
                adapter.Fill(ds);
            }
            finally
            {
                con.Close();
            }
            return ds;
        }


        static public DataSet UpdateMarks()
        {
            if ((pr[2] == null) || (pr[2] == "0") || (pr[1] == "-1"))
            {
                DataSet ds = new DataSet();
                return ds;
            }
            else
            {
                SqlCommand com = con.CreateCommand();
                com.CommandText = "SELECT [date] Дата, mark Оценка FROM marks WHERE (st_id = @St) AND (sbj_id = @Sbj)";
                com.Parameters.Clear();
                com.Parameters.Add("St", SqlDbType.Int).Value = int.Parse(pr[2]);
                com.Parameters.Add("Sbj", SqlDbType.Int).Value = int.Parse(pr[1]);
                DataSet ds = new DataSet();
                SqlDataAdapter adapter = new SqlDataAdapter(com);
                con.Open();
                try
                {
                    adapter.Fill(ds);
                }
                finally
                {
                    con.Close();
                }
               
                return ds;
            }
        }



        static public DataSet DataUpdate_comb()
        {
            SqlCommand com = con.CreateCommand();
            com.CommandText = "SELECT id, name FROM subjects";
            DataSet ds = new DataSet();
            SqlDataAdapter adapter = new SqlDataAdapter(com);
            con.Open();
            try
            {
                adapter.Fill(ds);
            }
            finally
            {
                con.Close();
            }
            return ds;
        }


        static public void dobavlenie_ozenki()
        {
            SqlCommand com = con.CreateCommand();
            com.CommandText = "INSERT INTO marks (st_id, sbj_id, [date], mark) VALUES (@StID, @SbjID, @Dat, @mMARK) ";
            com.Parameters.Clear();
            com.Parameters.Add("StID", SqlDbType.Int).Value = int.Parse(pr[1]);
            com.Parameters.Add("SbjID", SqlDbType.Int).Value = int.Parse(pr[2]);
            com.Parameters.Add("Dat", SqlDbType.DateTime).Value = pr[3];
            com.Parameters.Add("mMARK", SqlDbType.TinyInt).Value = int.Parse(pr[4]);
            DataSet ds = new DataSet();
            SqlDataAdapter adapter = new SqlDataAdapter(com);
            con.Open();
            try
            {
                adapter.Fill(ds);
            }
            finally
            {
                con.Close();
            }
        }


        static public void udalenie_ozenki()
        {
            SqlCommand com = con.CreateCommand();
            com.CommandText = "DELETE FROM marks WHERE (st_id=@StID) AND (sbj_id=@SbjID) AND ([date]=@Dat) AND ([mark]=@Oc)";
            com.Parameters.Clear();
            com.Parameters.Add("StID", SqlDbType.Int).Value = int.Parse(pr[1]);
            com.Parameters.Add("SbjID", SqlDbType.Int).Value = int.Parse(pr[2]);
            com.Parameters.Add("Dat", SqlDbType.DateTime).Value = DateTime.Parse(pr[3]);
            com.Parameters.Add("Oc", SqlDbType.Int).Value = int.Parse(pr[4]);

            DataSet ds = new DataSet();
            SqlDataAdapter adapter = new SqlDataAdapter(com);
            con.Open();
            try
            {
                adapter.Fill(ds);
            }
            finally
            {
                con.Close();
            }
        }

        static public void izmenenie_ozenki()
        {
            SqlCommand com = con.CreateCommand();
            com.CommandText = "UPDATE marks SET mark=@DBMark WHERE st_id=@StudID AND sbj_id=@PredID AND [date]=@DBDat";
            com.Parameters.Clear();
            com.Parameters.Add("DBMark", SqlDbType.Int).Value = int.Parse(pr[3]);
            com.Parameters.Add("StudID", SqlDbType.Int).Value = int.Parse(pr[1]);
            com.Parameters.Add("PredID", SqlDbType.Int).Value = int.Parse(pr[2]);
            com.Parameters.Add("DBDat", SqlDbType.DateTime).Value = DateTime.Parse(pr[4]);

            DataSet ds = new DataSet();
            SqlDataAdapter adapter = new SqlDataAdapter(com);
            con.Open();
            try
            {
                adapter.Fill(ds);
            }
            finally
            {
                con.Close();
            }
        }
        

        static public void wclient(Object cl)
        {
            
            int i = 0;
            int r = 0;
            TcpClient client = (TcpClient)cl;            
            
            NetworkStream stream = client.GetStream();
            
            otpr = "Соединение принято " + client.Client.RemoteEndPoint.ToString();
            rt.richTextBox1.Text = rt.richTextBox1.Text + otpr;
            BinaryFormatter bf = new BinaryFormatter();
                    while (true)
                    {
                        try
                        {                            
                            pr = (List<string>)bf.Deserialize(stream);
                            switch (Convert.ToInt32(pr[0]))
                            {

                                case 1:
                                    {
                                        bf.Serialize(stream, GetStudents());
                                        pr.Clear();
                                        break;
                                    }

                                case 2:
                                    {
                                        bf.Serialize(stream, DataUpdate_comb());
                                        pr.Clear();
                                        break;
                                    }

                                case 3:
                                    {
                                        bf.Serialize(stream, UpdateMarks());
                                        pr.Clear();
                                        break;
                                    }


                                case 4:
                                    {
                                        udalenie_ozenki();
                                        data = pr[2];
                                        pr[2] = pr[1];
                                        pr[1] = data;
                                        bf.Serialize(stream, UpdateMarks());
                                        pr.Clear();
                                        break;
                                    }
                                case 5:
                                    {
                                        izmenenie_ozenki();
                                        data = pr[2];
                                        pr[2] = pr[1];
                                        pr[1] = data;
                                        bf.Serialize(stream, UpdateMarks());
                                        pr.Clear();
                                        break;
                                    }

                                case 6:
                                    {
                                        dobavlenie_ozenki();
                                        data = pr[2];
                                        pr[2] = pr[1];
                                        pr[1] = data;
                                        bf.Serialize(stream, UpdateMarks());
                                        pr.Clear();
                                        break;
                                    }

                                case 0:
                                    {
                                        i = 1;
                                        break;
                                    }
                            }



                            data = null;
                            if (i == 1)
                            {
                                i = 0;
                                break;
                            }
                            r = pr.Count;
                        }
                        catch (Exception Ex)
                        {
                            MessageBox.Show("Соединиться не удалось. Причина:" + Ex);
                        }
            }
                    stream.Close();
                    client.Close();
        }
        static public void thread_listener()
        {
            Int32 port = Convert.ToInt32(rt.textBox1.Text);
            TcpListener server = null;
            IPAddress localAddr = IPAddress.Parse("127.0.0.1");
            server = new TcpListener(localAddr, port);

            server.Start();
            while (true)
            {
                TcpClient acc_client = server.AcceptTcpClient();
                Thread thread_cl = new Thread(wclient);
                thread_cl.Start(acc_client);
                
            }

            server.Stop();
        }


        private void button1_Click(object sender, EventArgs e)
        {
           
            Thread tt = new Thread(thread_listener);
            tt.Start();
           
        }

        private void label2_Click(object sender, EventArgs e)
        {

        }
    }
}



Добавлено через 2 минуты и 46 секунд
Надо чтобы выполнялась вот эта строка. Чтобы изменения в данном элементе происходили. А он показывает что да, изменения все произошли, параметр поменял свое значение, а на форме изменений не произошло(((
Код

rt.richTextBox1.Text = rt.richTextBox1.Text + otpr;

PM MAIL   Вверх
DVariuS
Дата 8.6.2009, 16:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 200
Регистрация: 10.2.2009
Где: Ukraine

Репутация: 5
Всего: 8



PM MAIL   Вверх
AGENTxXx
Дата 8.6.2009, 22:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 231
Регистрация: 8.6.2009

Репутация: нет
Всего: 1



Да, почитал я про это. Но все равно остался не в понятках. Может хотя бы кто ни будь сможет модифицировать чтобы хотя бы он был рабочий из MSDN. Попробывал несколько способов - так и не смог запустить! Хелп... Или хотя бы исходник на работу с этим методом или вообще где используется какая либо реализация для решения проблемы. ТУТ ведь есть ЗНАЮЩИЕ люди!!! А то сегодня можно сказать целый день потратил в пустую... совсем не гуд. Вот код из MSDNки
Код

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;

   public class MyFormControl : Form
   {
      public delegate void AddListItem(String myString);
      public AddListItem myDelegate;
      private Button myButton;
      private Thread myThread;
      private ListBox myListBox;
      public MyFormControl()
      {
         myButton = new Button();
         myListBox = new ListBox();
         myButton.Location = new Point(72, 160);
         myButton.Size = new Size(152, 32);
         myButton.TabIndex = 1;
         myButton.Text = "Add items in list box";
         myButton.Click += new EventHandler(Button_Click);
         myListBox.Location = new Point(48, 32);
         myListBox.Name = "myListBox";
         myListBox.Size = new Size(200, 95);
         myListBox.TabIndex = 2;
         ClientSize = new Size(292, 273);
         Controls.AddRange(new Control[] {myListBox,myButton});
         Text = " 'Control_Invoke' example ";
         myDelegate = new AddListItem(AddListItemMethod);
      }
      static void Main()
      {
         MyFormControl myForm = new MyFormControl();
         myForm.ShowDialog();
      }
      public void AddListItemMethod(String myString)
      {
            myListBox.Items.Add(myString);
      }
      private void Button_Click(object sender, EventArgs e)
      {
         myThread = new Thread(new ThreadStart(ThreadFunction));
         myThread.Start();
      }
      private void ThreadFunction()
      {
         MyThreadClass myThreadClassObject  = new MyThreadClass(this);
         myThreadClassObject.Run();
      }
   }
   public class MyThreadClass
   {
      MyFormControl myFormControl1;
      public MyThreadClass(MyFormControl myForm)
      {
         myFormControl1 = myForm;
      }
      String myString;

      public void Run()
      {


         for (int i = 1; i <= 5; i++)
         {
            myString = "Step number " + i.ToString() + " executed";
            Thread.Sleep(400);
            // Execute the specified delegate on the thread that owns
            // 'myFormControl1' control's underlying window handle with
            // the specified list of arguments.
            myFormControl1.Invoke(myFormControl1.myDelegate,
                                   new Object[] {myString});
         }
      }
   }

PM MAIL   Вверх
DVariuS
Дата 9.6.2009, 09:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 200
Регистрация: 10.2.2009
Где: Ukraine

Репутация: 5
Всего: 8



AGENTxXx, набросал тебе код для примера:
Код

        private void UpdateText(string text)   //создаем метод для изменения текста метки
        {
            label1.Text = text;
        }

        protected delegate void UpdateTextDelegate(string text);  //объявляем делегат для этого метода

        private void button1_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(ThreadMain);
            thread.Start();                                 //запускаем новый поток
        }

        private void ThreadMain()      //точка входа в новый поток
        {
            string newText = "text changed";
            Invoke(new UpdateTextDelegate(UpdateText), newText);  //выполняем делегат, содержащий наш метод, в основном потоке формы
        }

PM MAIL   Вверх
AGENTxXx
Дата 9.6.2009, 14:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 231
Регистрация: 8.6.2009

Репутация: нет
Всего: 1



Спасибо!!! Реализовать получилось. Принцеп вроде понял. Если не затруднит может кто ни будь подскажет как можно прервать выполнения потока, при нажатии на кнопку?
Вот код данной процедурки:
Код

static public void thread_listener()
        {
            Int32 port = Convert.ToInt32(rt.textBox1.Text);
            TcpListener server = null;
            IPAddress localAddr = IPAddress.Parse("127.0.0.1");
            server = new TcpListener(localAddr, port);

            server.Start();
            while (true)
            {
                TcpClient acc_client = server.AcceptTcpClient();
                Thread thread_cl = new Thread(wclient);
                thread_cl.Start(acc_client);
                
            }

            server.Stop();
        }

Проблема в том что даже после закрытия приложения (точнее самой формы) програма или если говорить в конкретном случае то сервер, продолжает работать. Так что каким то образом надо реализовать выход из цикла. Если ли у кого то какие то предложения? Меня затрудняет то, что после строчки:
Код

TcpClient acc_client = server.AcceptTcpClient();
 он просто останавливается и ждет запроса....
PM MAIL   Вверх
voodoo_alik
Дата 9.6.2009, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 13.4.2007

Репутация: нет
Всего: нет



Сделайте server.Stop() на сбытие FormClosing, предварительно вынеся server на уровень класса.
PM MAIL   Вверх
DVariuS
Дата 9.6.2009, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 200
Регистрация: 10.2.2009
Где: Ukraine

Репутация: 5
Всего: 8



Цитата(AGENTxXx @  9.6.2009,  14:24 Найти цитируемый пост)
Меня затрудняет то, что после строчки:

код C#
1:

TcpClient acc_client = server.AcceptTcpClient();


 он просто останавливается и ждет запроса.... 

1.Для управления подключением юзай TcpListener.BeginAcceptTcpClient

2. Сделай поток фоновым установкой свойства IsBackground:
Код

           Thread tt = new Thread(thread_listener);
            tt.IsBackground = true;
            tt.Start();

в таком случае поток будет завершаться при завершении приложения.

3. В цикле сделай вызов метода, который будет периодически проверять необходимость завершения потока. 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.4742 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.