2014-01-29 6 views
0

Я хочу запустить метод в пуле потоков. При создании следующего кода он дает ошибкуИспользование методов в пуле потоков

Перегрузка для 'метода' соответствует делегату 'System.Threading.WaitCallback'.

Я знаю, где происходит ошибка, но я не знаю, почему:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
namespace Thread_Pool 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      ThreadPool.QueueUserWorkItem(new WaitCallback(PrintNumbers)); 
      // PrintNumbers(); 
     } 
     static void PrintNumbers() 
     { 
      for (int i = 0; i < 10; i++) 
      { 
       Console.WriteLine(i); 
       Thread.Sleep(3000); 
      } 
     } 
    } 
} 

Когда приведенный выше код переписывается в следующем, она отлично работает.

static void PrintNumbers(object Stateinfo) 

Почему это происходит? Вместо использования объекта я могу использовать другой тип (например, int, float)?

ответ

1

Я знаю, где произошла ошибка, но я не знаю почему? когда выше кода переписано следующим образом, он отлично работает

Вы должны следовать singnature, которая требуется WaitCallback, как вы можете увидеть определение делегата от WaitCallback. Вот почему PrintNumbers должен иметь параметр типа object.

public delegate void WaitCallback(
    Object state 
) 

, почему это происходит? и вместо использования объекта я могу использовать другой тип (например, int, float)? Является ли это возможным?

Да, вы можете использовать Convert.ToDouble(obj);

0

Количество и тип аргументов должны соответствовать при создании делегатов.

В текущих версиях C# проще использовать лямбда-выражения, чем явно набранные делегаты.Это делает преобразование типов проще и позволяет передавать строго типизированных параметров

ThreadPool.QueueUserWorkItem(unused => PrintNumbers())); 

int intBalue = 1; 
double doubleValue = 2; 
ThreadPool.QueueUserWorkItem(unused => Method(intValue, doubleValue)); 

или вы можете пройти значение, как обычно:

ThreadPool.QueueUserWorkItem(state => MethodTakinObject(state)); 
1

Согласно MSDN

http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k(System.Threading.WaitCallback);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5);k(DevLang-csharp)&rd=true

WaitCallback делегатом хочет a Object аргумент:

[ComVisibleAttribute(true)] 
    public delegate void WaitCallback(Object state) 

Таким образом, вы должны предоставить его, даже если вы не собираетесь использовать его:

static void Main(string[] args) { 
    ThreadPool.QueueUserWorkItem(new WaitCallback(PrintNumbers)); 
    } 

    static void PrintNumbers(Object state) { // <- "Object state" is required here 
    ... 
    } 

Если вы хотите оставить PrintNumbers неповрежденной вы можете использовать лямбда:

static void Main(string[] args) { 
    ThreadPool.QueueUserWorkItem(
     (Object state) => { // <- You have to use "Object state" 
     PrintNumbers(); 
     } 
    ); 
    } 

    static void PrintNumbers() { 
    ... 
    } 
0

WaitCallback - это делегат, принимающий объект параметра. Для того, чтобы использовать делегат ваш метод должен соответствовать сигнатуре делегата следующим образом:

static void Main(string[] args) 
{ 
    ThreadPool.QueueUserWorkItem(new WaitCallback(PrintNumbers)); 

} 


static void PrintNumbers(object a) 
{ 
    for (int i = 0; i < 10; i++) 
    { 
     Console.WriteLine(i); 
     Thread.Sleep(3000); 
    } 
} 

или вы могли бы просто использовать лямбда-выражение

ThreadPool.QueueUserWorkItem(a => { PrintNumbers(); }); 

Функциональность мудры оба подхода являются одинаковыми. Аргумент «состояние» требуется только тогда, когда вы намерены передать значения в свой метод.

Смежные вопросы