2012-05-16 5 views
5

저는 멀티 스레딩을 처음 접했고 과거에는 그저 놀았습니다. 그러나 주 스레드에서 바이트 배열 목록을 가질 수 있고 여전히 별도의 스레드에서 새 바이트 배열을 만드는 동안 해당 목록에 추가 할 수 있으면 궁금합니다. 또한 for-each 루프를 사용하여 바이트 배열을 구문 분석하는 데 사용할 양식 목록을 살펴 보겠습니다. 그래서 기본적으로 의사 코드는 다음과 같을 것입니다.멀티 스레딩을 사용하는 동안 목록에 추가하는 방법은 무엇입니까?

reports = new List(); 

foreach (form in forms) 
{ 
    newReport = new Thread(ParseForm(form)); 
    reports.Add(newReport); 

} 

void ParseForm(form) 
{ 
    newArray = new byte[]; 
    newArray = Convert.ToBytes(form); 
    return newArray; 
} 

위의 의사 코드가 바람직 할 것입니다. 누구든지 이것이 가능하면 좋은 예를 들어 설명해 주면 실제 코드를 알아낼 수있을 것입니다.

+0

webservice는 .Net 3.5를 사용하고있어서, Tasks를 사용할 수 있다고 생각하지 않습니다. – jhorton

답변

3

, 또는 경우 SynchronizedCollection를 사용

또한 너무 명시 적으로 스레드의 생성을 방지하기 위해 Parallel.Foreach를 사용할 수 있습니다. NET 버전은 3.0 이상입니다. 여기

는 스레드가 액세스 할 컬렉션을 만드는 방법 중 하나입니다 :

SynchronizedCollection reports = new SynchronizedCollection(); 

foreach (form in forms) { 
    var reportThread = new Thread(() => ParseForm(form, reports)); 
    reportThread.Start(); 
} 

void ParseForm(Form form, SynchronizedCollection reports) { 
    newArray = new byte[]; 
    newArray = Convert.ToBytes(form); 
    reports.Add(newArray); 
} 

당신은 .NET 4 이상 수동으로 스레드를 관리하는 더 나은 대안이의 다양한 클래스에 의해 제공됩니다에있는 경우 System.Threading.Tasks 네임 스페이스 스레딩 구현을 결정하기 전에이 대안을 고려해보십시오.

+0

고맙습니다. SynchronizedCollection을 3.5에서 사용 중이므로 시도해야합니다. – jhorton

+0

SynchronizedCollection에 대한 참조를 설정해야합니까? Collections.Genereric 및 Threading에 대한 using 문이 있습니다. 그리고 그것이 3.5를 사용하고 있는지 확인했지만 SynchronizedCollection을 얻지 못했습니다. – jhorton

+0

@jhorton 'System.ServiceModel'에 대한 참조를 추가해야합니다. – dasblinkenlight

0

Why is enumerate files returning the same file more than once?

확인해보세요. 그것은 내가하고 싶은 것을 정확히 생각한다는 것을 보여줍니다.

메인 스레드에 목록을 작성한 다음 다른 스레드에서 추가합니다. 우리는 닷넷 3.5 깨달았다하기 전에

Files.Clear(); //List<string> 

Task.Factory.StartNew(() => 
{ 
     this.BeginInvoke(new Action(() => 
     { 
      Files.Add("Hi"); 
     })); 
}); 
+1

** this **가 System.Windows.Forms.Control (또는 파생 클래스) 인 경우에만 작동합니다. 이것은 동기화 메커니즘이 아니라 다른 스레드에서 UI와 상호 작용하는 방법입니다. –

+0

논쟁 할 수 없습니다. –

2

당신이 어떤 필요하지 않으면 닷넷 4

에 참조 할 수 있도록 유지 - 당신은

using System.Threading.Tasks 

이 필요할 것 주문 내에서 쉽게 "수정"하려면 목록 대신 ConcurrentBag<T> 클래스를 사용하는 것이 좋습니다. 더 많은 주문이 필요한 경우 ConcurrentQueue<T> 컬렉션도 있습니다.

사용자 정의가 더 필요한 경우 BlockingCollection <T>을 사용하여 사용자 고유의 차단 모음을 구현할 수 있습니다. 주제에 Here's a good article 여러 스레드에서 컬렉션에 액세스해야하는 경우 당신이해야 하나 사용 동기화,

private void ParseForms() 
{ 
    var reports = new ConcurrentBag<byte[]>(); 
    Parallel.ForEach(forms, (form) => 
           { 
            reports.Add(ParseForm(form)); 
           }); 

} 

private byte[] ParseForm(form) 
{ 
    newArray = new byte[]; 
    newArray = Convert.ToBytes(form); 
    return newArray; 
} 
+0

ConcurrentBag가 4.0 이상입니까? – jhorton

+0

예, 메모를 보았습니다. 이것은 .Net 4.0에서 사용하기가 쉽지 않은데 너무 쉽습니다. –

+0

거기에 동의해야합니다. 왜 그들이이 서비스를 4.0으로 업그레이드하지 않았는지 나는 확신하지 못합니다. 다른 모든 것은 그것을 사용하고 있습니다. – jhorton

0

다음은 C# 4.0에 액세스 할 수 없기 때문에 지금 막 채운 단순한 차단 모음 (대기열 전용)입니다. 그것은 4.0 동시 콜렉션보다 덜 효율적일 것이지만 충분히 잘 작동 할 것입니다. 모든 큐 메서드를 다시 구현하지 않고 그냥 큐에 넣고 큐에서 빼내고 들여다 보았습니다. 당신이 다른 사람들을 필요로하고 그들이 구현 될 방법을 이해할 수 없다면, 그것을 코멘트에 언급하십시오.

작업 블로킹 컬렉션이 있으면 일단 제작자 스레드에서 추가하고 소비자 스레드를 사용하여 제거 할 수 있습니다.

public class MyBlockingQueue<T> 
{ 
    private Queue<T> queue = new Queue<T>(); 
    private AutoResetEvent signal = new AutoResetEvent(false); 
    private object padLock = new object(); 

    public void Enqueue(T item) 
    { 
     lock (padLock) 
     { 
      queue.Enqueue(item); 
      signal.Set(); 
     } 
    } 

    public T Peek() 
    { 
     lock (padLock) 
     { 
      while (queue.Count < 1) 
      { 
       signal.WaitOne(); 
      } 

      return queue.Peek(); 
     } 
    } 

    public T Dequeue() 
    { 
     lock (padLock) 
     { 
      while (queue.Count < 1) 
      { 
       signal.WaitOne(); 
      } 

      return queue.Dequeue(); 
     } 
    } 
} 
관련 문제