java同步方法调用死锁_使用Task.Run同步调用异步方法最终导致死锁

我认为使用Task.Run调用异步方法不会导致任何死锁 . 但它确实:

async Task GetIdAsync()

{

return Task.Run( () => IncInt64Async( "id", 1L ) ).Result.ToString(); // Deadlock

}

async Task IncInt64Async( string key, Int64 inc );

我知道我应该等待 . 所以这个工作:

async Task GetIdAsync()

{

return await IncInt64Async( "id", 1L ); // of course, no deadlock.

}

但我只是想了解为什么第一次尝试导致死锁 . 在我对异步的理解中,只有当异步方法捕获同步上下文并尝试在上下文不能让它返回上下文时才会发生死锁 .

此外,在Task.Run()内部调用GetIdAsync(),因此无论如何它都在运行时没有同步上下文:

Task.Run( () => {

some code...

id = getIdAsync();

some code...

}

);

所以我疯了,尝试了我能想到的所有变化,但仍然所有尝试都会导致死锁:

Task.Run( () => IncInt64Async( "id", 1L ).ConfigureAwait(false).GetAwaiter().GetResult() ).ConfigureAwait(false).GetAwaiter().GetResult();

IncInt64Async( "id", 1L ).ConfigureAwait(false).GetAwaiter().GetResult();

Task.Run( () => IncInt64Async( "id", 1L ) ).Result;

Task.Run( () => IncInt64Async( "id", 1L ) ).ConfigureAwait(false).GetAwaiter().GetResult();

Task.Run( async () => await IncInt64Async( "id", inc ) ).ConfigureAwait(false).GetAwaiter().GetResult();

Task.Run( () => { var task = IncInt64Async( "id", inc ); task.Wait(); return task.Result; } ).Result;

BTW,在IncInt64Async的实现中,它使用了几个await而没有ConfigureAwait(false) .

可能是什么原因?

IncInt64Async()的实现:

async Task IncInt64Async( string key, Int64 value )

{

Task task = null;

byte error = 1;

byte[] bytes = null;

lock ( c.WriteLock )

{

c.Write( key, value );

_readTask = task = _readTask.ContinueWith( async o =>

{

if ( ( error = await c.ReadByteAsync() ) == 0 ) // **BLOCKS HERE**

{

bytes = new byte[ 8 ];

await c.ReadAsync( bytes, 0, 8 );

}

NumWaits--;

} ).Unwrap();

}

if ( task != null )

await task.AnyContext();

if ( error != 0 )

throw new InvalidOperationException();

return BitConverter.ToInt64( bytes, 0 );

}

'c'是TcpHandler的一个实例 .

它基本上是通过tcp写的,并从tcp读取 .

我正在使用ContinueWith()来对齐读取 . 我已经尝试将TaskScheduler.Default传递给ContinueWith() .

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值