2015-01-13 1 views
0

У меня есть интерфейс, который читает/записывает объект в хранилище. В одном случае хранилище представляет собой базу данных с асинхронными методами. В другом случае это всего лишь куки.Когда используется Task.Run расточительный или бредовый?

Полагаю, что рекомендуется использовать async обратно по пути, заканчивающемуся при вызове асинхронного вызова, поэтому кажется, что интерфейс также является асинхронным. Но в случае с файлом cookie я просто устанавливаю пару полей и вставляю их в ответ, так что там еще нет асинхронных сообщений. Я могу обернуть этот бит в ожидании Task.Run(), чтобы соответствовать новому интерфейсу, но я не знаю, является ли это целесообразным или имеет какое-то негативное влияние на производительность.

Что делать?

public interface IProfileStore 
{ 
    async Task SetProfile(UserProfile profile); 
} 

public async Task SetProfile(UserProfile profile) 
{ 
    // Look mom, I'm needlessly async 
    await Task.Run(() => 
    { 
     var cookie = new HttpCookie(AnonymousCookieName); 
     cookie["name"] = profile.FullName; 
     HttpContext.Current.Response.Cookies.Add(cookie); 
    }); 
} 
+0

Ну, каковы же шансы, что вы сможете заметить, что ваш код занимает нить TP за 30 наносекунд? Файлы cookie обычно работают с сетевыми соединениями, которые в * миллион раз больше латентности. –

+2

@James Я не думаю, что вы можете использовать модификатор 'async' для интерфейса. –

+0

Обратите внимание на статьи в [мой запрос async-wait] (http://curah.microsoft.com/45553/asyncawait-general). –

ответ

5

Вы не должны этого делать; вы просто создаете ненужный отбой.

Вместо этого удалите async ключевое слово из метода и просто return Task.FromResult(0) возвращать синхронно-завершенную задачу

+1

Это изменение семантики обработки исключений, так что исключения не будут завернуты в возвращаемую задачу. – Servy

+0

@Servy Необязательно для метода возврата задачи синхронно генерировать исключения. Возьмите 'Task.Delay', например ... – i3arnon

+1

@ I3arnon Я не сказал, что это было неправильно, просто потому, что он меняет семантику. Если пользователь хочет эту измененную семантику, это их решение. – Servy

1

Если вы выполняете очень короткую быстро завершила работу, то вы совершенно правы, что не существует, вероятно, нет необходимости использовать Task.Run подтолкнуть работу на другой поток. Акт планирования кода в пуле потоков, вероятно, займет больше времени, чем , просто делая это.

Как это сделать, просто удалите await Task.Run, который вам не нужен, и вуаля, вы все настроены. У вас есть синхронная операция, которая все еще завернута в Task и поэтому по-прежнему соответствует требуемому интерфейсу.

+0

Затем вы получите предупреждение о компиляторе. – SLaks

+0

@SLaks Да, вы это сделаете. Но так как вы узнаете, что ваш код верен, вы можете спокойно проигнорировать его. – Servy

+1

@SLaks Больше, чем предупреждение компилятора, у этого есть все накладные расходы на метод async, включая создание конечного автомата, который здесь не нужен. – i3arnon

1

Почти как следует SLaks, если вы делаете что-то асинхр но вернуть задачу, так:

public Task SetProfile(UserProfile profile) 
{ 
    return Task.Run(() => 
    { 
     var cookie = new HttpCookie(AnonymousCookieName); 
     cookie["name"] = profile.FullName; 
     HttpContext.Current.Response.Cookies.Add(cookie); 
    }); 
} 

Однако, как он говорит в этом случае:

public Task SetProfile(UserProfile profile) 
{ 
    var cookie = new HttpCookie(AnonymousCookieName); 
    cookie["name"] = profile.FullName; 
    HttpContext.Current.Response.Cookies.Add(cookie); 
    return Task.FromResult(null); 
} 

Возврат нуль в качестве своей системы кешированные завершения задачи.

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