【发布时间】:2016-12-12 09:51:56
【问题描述】:
首先我想说,如果这是一个不好的问题,我很抱歉。今天早上早些时候我有一个关于这个问题的问题,可以解决一些问题,但我仍然陷入僵局,我整个早上都在努力解决这个问题。
我正在尝试从服务器请求聊天。在 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();
}
requestChats 在我的 UWP WebsocketManager 中看起来像这样:
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 - 信息:数据已发送
对不起,问题太长了,我试图只显示死锁的相关代码。
编辑 1:
我在 cmets 中尝试了 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 - 信息:正在尝试发送数据...请求聊天
13.12.2016 07:55:32 - 错误:在意外时间调用了一个方法。 (HRESULT 异常:0x8000000E)
13.12.2016 07:55:32 - 信息:dataWriter 已处理 requestChats。
13.12.2016 07:55:32 - 信息:正在尝试发送数据...请求联系人
13.12.2016 07:55:32 - 信息:dataWriter 已初始化 requestContacts。
【问题讨论】:
-
0x8000000E错误表示您的异步操作没有完成但您尝试获取结果。 -
您是否正在尝试存储/写入流并且多个线程正在访问同一个流。您需要放置一个信号量:await dataWriter.StoreAsync();
-
@AzharKhorasany 感谢您的建议。我试过了,但没有解决问题。我已经编辑了我的问题
-
@AzharKhorasany 实际上我发现我做错了,我应该已经使用
requestChats中的信号量了......抱歉,现在试试 -
你的 dataWriter 实例化在哪里?你不能在 SendData() 方法中实例化它吗?不应共享 DataWriter。它应该实例化、完成它的工作并被处理掉。
标签: c# asynchronous deadlock