2012-06-27 3 views
0

으로 대리자를 작성하는이 작품 :는 Func을

//delegate 
    Parallel.For(1023456789, 1033456789, delegate(long i) 
      { 
       if (i % 10000000 == 0) Console.WriteLine("{0:N0}", i); 
       if (IsPanDigital(i)) 
       { 
        list.Add(i); 
       } 
      } 
     ); 

    //lambda expression 
    Parallel.For(1023456789, 1033456789, i => 
      { 
       if (i%10000000 == 0) Console.WriteLine("{0:N0}", i); 
       if (IsPanDigital(i)) 
       { 
        list.Add(i); 
       } 
      } 
     ); 

그것은 Func을 사용하여이 논리를 다시 할 수 있습니까? 나는 여기에서 시도했다. .. 컴파일하지 않는다.

var list = new List<long>(); 
    Parallel.For(1023456789, 1033456789, Blah(i, ref list)); 

public static Func<long> Blah(long i, ref List<long> list) 
{ 
    if (i % 10000000 == 0) Console.WriteLine("{0:N0}", i); 
    if (IsPanDigital(i)) 
    { 
     list.Add(i); 
    } 
} 

시도 할 수 있는지 확인하려고합니다.

+0

어떤 컴파일 오류가 발생 했습니까? –

+3

여러 스레드에서 병렬로 목록에 추가하는 것은 스레드로부터 안전하지 않습니다. – dtb

+2

'list' 매개 변수가 참조로 전달되는 이유는 무엇입니까? 어디서나 값을 변경하지 않습니다 ... –

답변

7

당신은 거의 그것을했다 :

public static void Blah(long i, ref List<long> list) 
{ 
    if (i % 10000000 == 0) Console.WriteLine("{0:N0}", i); 
    if (IsPanDigital(i)) 
    { 
     list.Add(i); 
    } 
} 

var list = new List<long>(); 
Parallel.For(1023456789, 1033456789, i => Blah(i, ref list)); 

은 (내가 voidBlah의 반환 유형을 변경하고 Action<long>을 일치시킬 수 있도록 람다에서 그것을 포장 i => 추가)

편집 : 또는 변경 Action<long>-Blah과 다른 사소한 리팩토링을 수행

public static Action<long> Blah(List<long> list) 
{ 
    return i => 
    { 
     if (i % 10000000 == 0) Console.WriteLine("{0:N0}", i); 
     if (IsPanDigital(i)) 
     { 
      list.Add(i); 
     } 
    }; 
} 

var list = new List<long>(); 
Parallel.For(1023456789, 1033456789, Blah(list)); 

을 나는이 두 번째 예가 당신이 성취하려고했던 것과 더 가깝다고 생각합니다.

@lee 지적했듯이 적어도 표시된 코드에서 ref 매개 변수는 필요하지 않습니다. ref 매개 변수도 lambdas 내부에서 사용할 수 없으므로 컴파일러 오류가 발생하여 제거했습니다. ref을 실제로 사용해야하는 경우 첫 번째 예로 이동하십시오. Func<T>T 값을 반환 뭔가이며, Parallel 무효 반환하는 Action<T>을 찾고 있기 때문에 당신이 Func을 사용할 수 없습니다

이유입니다.

@dtb 매우 중요한 점을 지적했다. "병렬로 여러 스레드에서 목록에 추가하는 것은 스레드로부터 안전하지 않습니다." list.Add 메소드를 잠그고 private static object으로 잠그면 문제를 해결할 수 있습니다. 나는 당신의 작품 대부분이 IsPanDigital을 계산하고 있다고 생각합니다. 그래서 이것이 합리적이라고 생각합니다.

+1

'list' 인수에'ref' 수정자가 필요 없습니다. – Lee

+0

답변/댓글을 달아 준 모든 분들께 감사드립니다. ref ...에 의해 합격.... 그것은 전혀 필요로하지 않았다. 지금은 명확성을 좋아하기 때문에 위임 구문을 고수 할 것입니다. –

1

나는 당신이 그것으로 뭘 원하는지 잘 모릅니다 만, 함수 모자

  • 정적
  • 무효 이름이 여기

를 컴파일하는 코드이다 (I를 INT)
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 

     static List<long> list = new List<long>(); 

     static void Main(string[] args) 
     { 


      //delegate 
      Parallel.For(1023456789, 1033456789, delegate(long i) 
      { 
       if (i % 10000000 == 0) Console.WriteLine("{0:N0}", i); 
       if (IsPanDigital(i)) 
       { 
        list.Add(i); 
       } 
      }); 

      //lambda expression 
      Parallel.For(1023456789, 1033456789, i => 
      { 
       if (i % 10000000 == 0) Console.WriteLine("{0:N0}", i); 
       if (IsPanDigital(i)) 
       { 
        list.Add(i); 
       } 
      }); 

      Parallel.For(1023456789, 1033456789, Blah); //other overloads do accept other Actions 

     } 

     private static bool IsPanDigital(long i) 
     { 
      return false; 
     } 

     public static void Blah(int i) // = Action<int i> 
     { 
      if (i % 10000000 == 0) Console.WriteLine("{0:N0}", i); 
      if (IsPanDigital(i)) 
      { 
       list.Add(i); 
      } 
     } 
    } 
} 
관련 문제