首先,我想说,如果这是一个糟糕的问题,我很抱歉。今天早上我有一个关于这个问题的问题并且可以解决一些问题,但我仍然陷入僵局,整个上午我都在努力解决这个问题。
我正在尝试从服务器请求聊天。在UWP中,我需要异步执行此操作。我的方法在大约每5次尝试时就会导致死锁,我正在运行以下代码。
第一次等待发生在OnNavigatedTo
:
public async void OnNavigatedTo(NavigationParameters parameters)
{
IsLoadMoreItemsPossible = true;
if (_first)
{
_first = false;
await LoadDataTaskAsync();
}
}
调用LoadDataTaskAsync
:
private async Task LoadDataTaskAsync()
{
if (IsBusy)
{
return;
}
IsLoadMoreItemsPossible = false;
IsBusy = true;
IsFree = false;
if (!CommonUtils.isInternetAvailable())
{
// load from local
}
await _remoteDataManager.requestChats();
}
_remoteDataManager.requestChats()
为当前平台获取正确的方法:
public async Task requestChats()
{
await _websocketManager.requestChats();
}
我的UWP WebsocketManager中的 requestChats
如下所示:
public async Task requestChats()
{
dataWriter.WriteString(WebsocketRequestFactory.Create(SocketEventsEnm.GET_CHATS));
await SendData(dataWriter);
}
最后SendData
,异常发生的地方:
private async Task SendData(DataWriter dataWriter)
{
try
{
_evaLogger.Info("Trying to send data...");
await dataWriter.StoreAsync(); // This is where the exception occurs
_evaLogger.Info("Data was sent");
}
catch (Exception e)
{
_evaLogger.Error(e.Message, e);
}
}
_evaLogger
写入日志文件,该日志文件在发生死锁时记录:
12.12.2016 10:38:08 - 信息:Websocket已打开
12.12.2016 10:38:08 - 信息:尝试发送数据......
12.12.2016 10:38:08 - 错误:在意外时间调用了一个方法。 (来自HRESULT的异常:0x8000000E)
12.12.2016 10:38:09 - 信息:尝试发送数据......
12.12.2016 10:38:09 - 信息:已发送数据
很抱歉这个很长的问题,我试图只显示死锁的相关代码。
我在评论中尝试了Azhar Khorasany的建议,以便在访问流时使用信号量:
public class AsyncLock
{
public readonly AsyncSemaphore m_semaphore;
private readonly Task<Releaser> m_releaser;
public AsyncLock()
{
m_semaphore = new AsyncSemaphore(1);
m_releaser = Task.FromResult(new Releaser(this));
}
public Task<Releaser> LockAsync()
{
var wait = m_semaphore.WaitAsync();
return wait.IsCompleted ?
m_releaser :
wait.ContinueWith((_, state) => new Releaser((AsyncLock)state),
this, CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
}
}
新requestChats
方法:
private static readonly AsyncLock m_lock = new AsyncLock();
public async Task requestChats()
{
using (await m_lock.LockAsync())
{
using (DataWriter dataWriter = new DataWriter(messageWebsocket.OutputStream))
{
_evaLogger.Info("dataWriter initialized requestChats.");
dataWriter.WriteString(WebsocketRequestFactory.Create(SocketEventsEnm.GET_CHATS));
await SendData(dataWriter, "requestChats");
}
}
_evaLogger.Info("dataWriter disposed requestChats.");
}
不幸的是,它没有解决死锁问题:
13.12.2016 07:55:31 - 信息:Websocket已打开
13.12.2016 07:55:32 - 信息:dataWriter初始化了requestChats。
13.12.2016 07:55:32 - 信息:尝试发送数据... requestChats
13.12.2016 07:55:32 - 错误:在意外时间调用了一个方法。 (来自HRESULT的异常:0x8000000E)
13.12.2016 07:55:32 - 信息:dataWriter处理了requestChats。
13.12.2016 07:55:32 - 信息:尝试发送数据... requestContacts
13.12.2016 07:55:32 - 信息:dataWriter初始化了requestContacts。
答案 0 :(得分:1)
此代码中存在几个潜在问题,因为它显然不是用并行线程编写的。从我的代码中我可以看出,你的直接问题是线程之间共享dataWriter
。想象一下,当另一个线程正在执行dataWriter.WriteString(...)
时,一个线程可能正在执行dataWriter.StoreAsync()
并且您看到了问题。您需要了解并行编程,并充分了解代码的执行方式。像IsBusy
这样的标志可以&#34;工作&#34;在一个单线程程序中,只要你有多个线程,它就会让你头疼。
快速建议您的代码:
删除dataWriter
的全局声明并更改以下代码:
public async Task requestChats()
{
/* declare dataWriter here so it becomes an instance variable*/
dataWriter.WriteString(WebsocketRequestFactory.Create(SocketEventsEnm.GET_CHATS));
await SendData(dataWriter);