728x90
반응형
728x170
작업 조건이 아래와 같은 경우를 위한 비동기 순차 처리 코드이다.
- 1번 쓰기 작업 완료 후 1번 읽기 작업을 할 수 있고 2번 쓰기 작업 완료 후 2번 읽기 작업을 할 수 있다.
- 1번 쓰기 작업 완료 후 2번 쓰기 작업을 할 수 있고 2번 쓰기 작업 완료 후 3번 쓰기 작업을 할 수 있다.
- 1번 읽기 작업 완료 후 2번 읽기 작업을 할 수 있고 2번 읽기 작업 완료 후 3번 읽기 작업을 할 수 있다.
- 쓰기 작업은 동시에 50개까지 할 수 있다.
- 읽기 작업은 동시에 50개까지 할 수 있다.
- 모든 쓰기/읽기 작업이 완료될 때까지 프로그램 종료를 보류한다.
728x90
▶ Program.cs
using System;
using System.Collections.Generic;
using System.Threading;
namespace TestProject
{
/// <summary>
/// 프로그램
/// </summary>
class Program
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 난수 발생기
/// </summary>
/// <remarks>작업 시간을 임의로 설정하기 위한 것이다.</remarks>
private static Random _random = null;
/// <summary>
/// 쓰기 자동 리셋 이벤트 딕셔너리
/// </summary>
/// <remarks>첫번째 쓰기 작업이 끝나기 전에 두번째 쓰기 작업이 시작되는 것을 방지하기 위한 것이다.</remarks>
private static Dictionary<int, AutoResetEvent> _writeAutoResetEventDictionary = null;
/// <summary>
/// 읽기 자동 리셋 이벤트 딕셔너리
/// </summary>
/// <remarks>첫번째 읽기 작업이 끝나기 전에 두번째 읽기 작업이 시작되는 것을 방지하기 위한 것이다.</remarks>
private static Dictionary<int, AutoResetEvent> _readAutoResetEventDictionary = null;
/// <summary>
/// 카운트 다운 이벤트
/// </summary>
/// <remarks>모든 쓰기/읽기 작업이 완료될 때까지 대기하기 위한 것이다.</remarks>
private static CountdownEvent _countdownEvent = null;
/// <summary>
/// 쓰기 세마포어
/// </summary>
/// <remarks>동시에 처리 가능한 쓰기 작업 수를 제한하기 위한 것이다.</remarks>
private static SemaphoreSlim _writeSemaphore = new SemaphoreSlim(50);
/// <summary>
/// 읽기 세마포어
/// </summary>
/// <remarks>동시에 처리 가능한 읽기 작업 수를 제한하기 위한 것이다.</remarks>
private static SemaphoreSlim _readSemaphore = new SemaphoreSlim(50);
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Private
#region 데이터 쓰기 - WriteData(parameter)
/// <summary>
/// 데이터 쓰기
/// </summary>
/// <param name="parameter">매개 변수</param>
private static void WriteData(object parameter)
{
int i = (int)parameter;
try
{
if(i > 0)
{
_writeAutoResetEventDictionary[i - 1].WaitOne();
}
// 임의 작업을 한 것으로 가정한다.
Thread.Sleep(_random.Next(30, 100));
Console.WriteLine(i.ToString() + "번 쓰기 작업을 완료했습니다.");
_readSemaphore.Wait();
Thread thread = new Thread(new ParameterizedThreadStart(ReadData));
thread.Start(i);
}
finally
{
_writeAutoResetEventDictionary[i].Set();
_writeSemaphore.Release();
}
}
#endregion
#region 데이터 읽기 - ReadData(Parameter)
/// <summary>
/// 데이터 읽기
/// </summary>
/// <param name="parameter">매개 변수</param>
private static void ReadData(object parameter)
{
int i = (int)parameter;
try
{
if(i > 0)
{
_readAutoResetEventDictionary[i - 1].WaitOne();
}
Thread.Sleep(_random.Next(30, 100));
Console.WriteLine(i.ToString() + " 차트 읽기 작업을 완료했습니다.");
}
finally
{
_readAutoResetEventDictionary[i].Set();
_countdownEvent.Signal();
_readSemaphore.Release();
}
}
#endregion
#region 프로그램 시작하기 - Main()
/// <summary>
/// 프로그램 시작하기
/// </summary>
private static void Main()
{
_random = new Random();
// 처리할 작업 수를 설정한다.
int threadCount = 100;
// 작업을 순차적으로 처리하기 위한 쓰기/읽기 동기 객체 딕셔너리를 초기화 한다.
_writeAutoResetEventDictionary = new Dictionary<int, AutoResetEvent>();
_readAutoResetEventDictionary = new Dictionary<int, AutoResetEvent>();
for(int i = 0; i < threadCount; i++)
{
_writeAutoResetEventDictionary.Add(i, new AutoResetEvent(false));
_readAutoResetEventDictionary.Add(i, new AutoResetEvent(false));
}
// 모든 쓰기/읽기 작업이 완료될 때까지 대기하기 위한 동기 객체를 초기화 한다.
_countdownEvent = new CountdownEvent(threadCount);
// 작업을 처리한다.
for(int i = 0; i < threadCount; i++)
{
Console.WriteLine(i.ToString() + "번 작업을 시작합니다.");
_writeSemaphore.Wait();
Thread writeThread = new Thread(new ParameterizedThreadStart(WriteData));
writeThread.Start(i);
Thread.Sleep(200);
}
// 모든 쓰기/읽기 작업이 완료될 때까지 대기한다.
_countdownEvent.Wait();
Console.WriteLine("작업을 완료했습니다.");
}
#endregion
}
}
728x90
반응형
그리드형(광고전용)
'C# > Common' 카테고리의 다른 글
[C#/COMMON] ServiceController 클래스 : 윈도우즈 서비스 설치 여부 구하기 (0) | 2016.06.12 |
---|---|
[C#/COMMON] ServiceController 클래스 : 윈도우즈 서비스 재시작하기 (0) | 2016.06.12 |
[C#/COMMON] ServiceController 클래스 : 윈도우즈 서비스 중단하기 (0) | 2016.06.12 |
[C#/COMMON] ServiceController 클래스 : 윈도우즈 서비스 시작하기 (0) | 2016.06.12 |
[C#/COMMON] EventLog 클래스 : 이벤트 로그 사용하기 (0) | 2016.06.12 |
[C#/COMMON] Timer 클래스 사용하기 (0) | 2016.06.04 |
[C#/COMMON] ThreadPool 클래스 : RegisterWaitForSingleObject 메소드를 사용해 타임아웃 사용하기 (0) | 2016.06.04 |
[C#/COMMON] ThreadPool 클래스 : 취소 옵션 사용하기 (0) | 2016.06.04 |
[C#/COMMON] ThreadPool 클래스 : 비동기 호출하기 (0) | 2016.06.04 |
[C#/COMMON] 대리자를 사용해 비동기 호출하기 (0) | 2016.06.04 |
댓글을 달아 주세요