📜 ⬆️ ⬇️

The practice of using the System.Threading space when writing multi-threaded applications in .NET.

Recently, you have to write "small" servers for multi-threaded processing of relatively small amounts of data. I want to share with the habrasoobshchestvom certain technique in writing such applications.

All tasks can be formalized into these 3 points:
1. There is a data set.
2. These data need to be processed (we do not care how and what to process, the main thing is to do it in parallel).
3. Data is constantly coming new.
To illustrate certain points, let's solve the problem of sampling data from a variety of RSS feeds.
I cited the solution to this problem in the following code, which can be simply copied and run, a code with comments that I hope can easily describe certain points.

using System;
using System.Collections. Generic ;
using System.Text;
using System.Threading;
using System.Net;
using System.IO;

namespace ConsoleApplication1
{
class Program
{
internal class RSSServer
{
//
private Thread _server;

//
private bool _start = false ;

// RSS
public List < string > ResultData
{
get ;
set ;
}

#region

private int _countAll = 0; //
private int _countEnd = 0; //

#endregion

// -
private ManualResetEvent _mre = new ManualResetEvent( false );

/// <summary>
///
/// </summary>
private void GetTask()
{
string [] _rssURLs;

/* "" , */
while (_start)
{
_rssURLs = GetURLs(); //
if (_rssURLs.Length > 0) // ,
{
_mre.Reset(); // , , WaitOne
_countAll = _rssURLs.Length; // , ..
_countEnd = 0; // , .. 0,
ResultData = new List < string >(_countAll);
foreach ( string s in _rssURLs) // .
{
ProccessingRSS(s);
}
_mre.WaitOne(); // ,
foreach ( string x in ResultData)
{
Console .WriteLine(x);
}
/* ,
* .. ResultData
*
*/
break ;
}
else
{
/* , .
* 200 , ,
* 50%, . .
* ,
* 1 , ,
* ( ), .
*/
Thread.Sleep(200);
}

}
}

private void ProccessingRSS( string _rssURL)
{
/*
* . .
*/
ThreadPool.QueueUserWorkItem( new WaitCallback(ProcRSS), _rssURL);
}

private void ProcRSS( object rss)
{
// try
try
{
string _rss = ( string )rss;
HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create(_rss);
HttpWebResponse hwrr = (HttpWebResponse)hwr.GetResponse();
string response = ( new StreamReader(hwrr.GetResponseStream())).ReadToEnd();
// ,
lock (ResultData)
{
ResultData.Add(response);
}
}
catch
{
// ( )
}
finally
{
Interlocked.Increment( ref _countEnd); // , , ..
if (_countEnd >= _countAll) // , ,
_mre.Set();
}
}

private string [] GetURLs()
{
return new string [2] { "http://habrahabr.ru/rss/" , "http://www.cbr.ru/scripts/RssPress.asp" }; // , .
}

public void StartServer()
{
_server = new Thread( new ThreadStart(GetTask));

// true, ,
// , , ,
// ""
_server.IsBackground = true ;

// ,
// ,
_server.Name = "GetTaskThread" ;

// ,
if ((_server.ThreadState & ThreadState.Unstarted) == ThreadState.Unstarted)
{
_start = true ; // true,
_server.Start();
}
}

public void StopServer()
{
_start = false ;
}
}

static void Main( string [] args)
{
RSSServer _rServer = new RSSServer();
_rServer.StartServer();
Console .Read();
_rServer.StopServer();
}
}
}

* This source code was highlighted with Source Code Highlighter .


This article is aimed at those people who still do not fully understand how to work with the System.Threading space. If you have any questions, ask them in comments, I will try to answer.
')

Source: https://habr.com/ru/post/47317/


All Articles