2013-03-11 7 views
0

Я разрабатываю приложение для Android и использую SignalR на моем сервере asp.net и пользовательском java-клиенте SignalA. Я столкнулся со следующей проблемой: когда клиент присоединяется к какой-либо группе, он не получает сообщение, которое отправляется сразу после присоединения. Вот кусок кода с сервера:SignalR: объединение группы синхронизации

Task.Factory.StartNew(() => context.Groups.Add(groupId, connectionId)). 
    ContinueWith(t => Groups.Send(groupId, message)); 

На клиентской стороне я получаю обратный вызов с новыми группами лексем, но первое отправленное сообщение не получено (сообщения, отправленные после этого, однако, получили). Попытка того же самого с официальным клиентом C# работает отлично. Таким образом, кажется, что первое сообщение получено до того, как будет обработан новый токен групп.

После долгих попыток сравнения кода кода C# и java я не нашел решение. Я ищу объяснение (или ссылки на код) о том, как эта ситуация обрабатывается на клиенте C#, поэтому я смогу реализовать ту же логику в java-клиенте.

P.S. было бы гораздо более безболезненно, если бы использовался официальный клиент C# с андроидом вместо использования пользовательского java-клиента.

P.P.S. есть некоторые «грязные» способы исправить мою проблему, например, положить небольшую задержку на сервер после присоединения к группе или отправить сообщение подтверждения от клиента, но все же я ищу «чистое» исправление.

ответ

5

Нет причин для использования Task.Factory.StartNew.

context.Groups.Add(connectionId, groupName) уже возвращает Task, что вы должны ждать, прежде чем отправить сообщение groupName, что вы ожидаете клиента, идентифицированный connectionId.

Когда вы звоните

Task.Factory.StartNew(() => context.Groups.Add(connectionId, groupName)) 

вы получите Task<Task>.

Это означает, что при вызове Groups.Send(groupName, message)ContinueWith внутри, только внешняя задача завершена, и connectionId еще не был полностью добавлен в groupdName.

Если вы работаете в .NET 4.5, самый простой способ переписать этот код, чтобы использовать асинхронный/ОЖИДАНИЕ рисунок как так:

public async Task AddToGroupAndSend(IPersistentConnectionContext context, 
            string connectionId, 
            string groupName, 
            object message) 
{ 
    await context.Groups.Add(connectionId, groupName); 
    await context.Groups.Send(groupName, message); 
} 

Если вы работаете в .NET 4.0 вы можете продолжать использовать ContinueWith, но без Task.Factory.StartNew:

public Task AddToGroupAndSend(IPersistentConnectionContext context, 
           string connectionId, 
           string groupName, 
           object message) 
{ 
    // This doesn't appropriately handle faulted or canceled tasks 
    return context.Groups.Add(connectionId, groupName) 
        .ContinueWith(t => groups.Send(groupName, message)); 
} 

Если вы не против того, код выполнять синхронно можно даже сделать следующее:

public void AddToGroupAndSend(IPersistentConnectionContext context, 
           string connectionId, 
           string groupName, 
           object message) 
{ 
    context.Groups.Add(connectionId, groupName).Wait(). 
    groups.Send(groupName, message).Wait(); 
} 

ПРИМЕЧАНИЕ: В моих примерах connectionId является первым аргументом context.Groups.Add и groupName является вторым. Это правильный порядок для этих параметров и противоположность тому, как вы написали его в своем вопросе.

Я не знаю, почему ваш предыдущий код работал с клиентом C#, но не с Java. Учитывая код, указанный в вашем вопросе, я ожидаю, что любой клиент пропустит первое отправленное сообщение.

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