2016-10-17 2 views
2

Я случайно столкнулся с проблемой, которую я смог решить. Тем не менее, меня беспокоит моя неспособность понять, почему код с ошибкой смог скомпилировать (на первом месте).Параметрированное действие

Ниже приводится код ошибки-й изд, что компилируется нормально:

Task<string> myTask = Task<string>.Factory.StartNew(() => 
      { 
       System.Threading.Thread.Sleep(1000); 
       return "mystrineg"; 
      }); 
      myTask.ContinueWith(t => action, CancellationToken.None, 
       TaskContinuationOptions.NotOnFaulted, TaskScheduler.Default); 

Проблема с выше кодом: action не будет вызываться. Вот исправление я сделал:

Task<string> myTask = Task<string>.Factory.StartNew(() => 
      { 
       System.Threading.Thread.Sleep(1000); 
       return "mystrineg"; 
      }); 
      myTask.ContinueWith(t => action(t.Result), CancellationToken.None, 
       TaskContinuationOptions.NotOnFaulted, TaskScheduler.Default); 

Мой вопрос, почему компилятор позволяет вызывать параметризованным действие без аргумента?

+0

Все ответы правы. Однако я должен был выбрать тот, который прибыл раньше и был ясен. Спасибо вам всем! – James

ответ

2

Вопрос в том, почему компилятор позволяет вызвать параметризованное действие без аргумента?

Это не так. В вашей первой версии вы вообще не вызывали action. Даже без аргументов. Вам нужно было бы передать его напрямую без лямбды или называть его пустой парой (), чтобы на самом деле назвать это.

Хотя action; не будет действительным заявление, .ContinueWith будет не только принимать Action<Task>, но и Func<Task, T> и это именно то, что вы прошли ... функция принимает задачу, возвращая любой тип вашей action имеет: t => action;

2
t => action 

короткий для:

t => { return action; } 

отсюда и результат.

3

Ваш первый код будет использовать этот overload, и что он будет делать, это вернуть делегат действия и вообще не будет его выполнять.

Перегрузкой, в которой вы действительно нуждаетесь, является this, и ваш второй код фактически использует его и выполнит ваше действие.

Мне интересно, почему вы не использовали async and await вместо ContinueWith и Task.Run вместо Task.Factory.StartNew, который может быть dangerous.

Ваш код может быть гораздо проще:

Task<string> myTask = Task.Run(() => 
         { 
          System.Threading.Thread.Sleep(1000); 
          return "mystrineg"; 
         }); 
string str = await myTask; 
action(str); 
+0

Очень действительная точка. Однако код старый, и нет возможности использовать .Net 4.5. – James