我目前正在升级一些现有代码以供Windows通用使用,并且我正在努力转换命令模式以使用新的异步/等待功能。
我有一个命令调度程序类,它在自己的线程中运行并处理已添加到其队列中的命令。有问题的方法如下:
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
role_hierarchy:
ROlE_Client: ROLE_Client
ROlE_Agent: ROLE_Agent
ROLE_SUPER_ADMIN: ROLE_SUPER_ADMIN
providers:
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
#always_use_default_target_path: false
#default_target_path: /affichage
logout: true
anonymous: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
- { path: ^/affichage, role: ROLE_Agent }
我的问题是我的一些ICommandItem.Execute()方法现在需要异步,因为它们涉及文件io而其他人没有异步方法。我怎样才能修改上面的模式:
我很乐意同步执行这些方法但现在到处都会造成死锁。
答案 0 :(得分:6)
我的问题是我的一些ICommandItem.Execute()方法现在需要异步,因为它们涉及文件io,而其他人没有异步方法。
从技术上讲,异步(Task
- 返回)签名仅表示实现可能是异步的。因此,虽然您可以引入单独的异步接口,但另一种方法是将现有接口更改为Task
- 返回:
interface ICommandItem
{
Task ExecuteAsync(); // Used to be "void Execute();"
}
您的同步实施必须更改为返回Task
:
Task ICommandItem.ExecuteAsync()
{
// Do synchronous work.
return Task.CompletedTask; // If you're not on 4.6 yet, you can use "Task.FromResult(0)"
}
虽然异步实现很简单:
async Task ICommandItem.ExecuteAsync()
{
await ...; // Do asynchronous work.
}
和你的"跑步者"可以使用await
:
private async Task ProcessCommandsAsync()
{
while(_items.count > 0)
{
await _items[0].ExecuteAsync();
_items.RemoveAt(0);
}
}
答案 1 :(得分:0)
您可以提供第二个接口IAsyncCommandItem:
public interface IAsyncCommandItem : ICommandItem
{
}
在while循环中,检查项目是否实现了此接口,并处理它:
private async void ProcessCommands()
{
while(_items.count > 0)
{
var command = _items[0] as IAsyncCommandItem;
if (command != null)
{
await command.Execute();
}
else
{
_items[0].Execute();
}
_items.RemoveAt(0);
}
}
当然,这假定您可以自由修改特定的命令类来实现新接口。