简体   繁体   English

异步命令Wpf C#

[英]Async Command Wpf C#

The program has an update button which sends a request to the server. 该程序具有一个更新按钮,该按钮将请求发送到服务器。 My task is that when you click on the button, the request to the server is started in a separate asynchronous thread, and on the user interface (wpf) a image "spinner-loading" appears. 我的任务是,当您单击该按钮时,将在单独的异步线程中启动对服务器的请求,并且在用户界面(wpf)上会出现“旋转加载”图像。 I get an error: 我收到一个错误:

"Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type". “无法将lambda表达式转换为预期的委托类型,因为该块中的某些返回类型不能隐式转换为委托返回类型”。

How can I combine async and void or, can I do something any better? 如何将asyncvoid结合起来,或者我可以做得更好?

ViewModel: ViewModel:

public CarasViewModel()
    {
      ...
     AddCommand = new AsyncCommand<Task>(() => Add());
      ...
    }

public IAsyncCommand AddCommand { get; private set; }
    async Task Add()
    {
        await Task.Run(() => OnAdd());
    }

void OnAdd()
    {
        var Result = Helper.Get(Configuration.Settings);
        if (Result != null)
        {
            var SelectionViewModel = new SelectionViewModel(Result);
            if (DialogService.ShowModalWindow(selectionViewModel))
            {
                ...
            }
        }
        else
        {
            MessageBoxService.ShowError("Check your connection settings.");
        }
    }

code snippet AsyncCommand: 代码段AsyncCommand:

public class AsyncCommand<TResult> : AsyncCommandBase, INotifyPropertyChanged
{
    private readonly Func<Task<TResult>> _command;
    private NotifyTaskCompletion<TResult> _execution;

    public AsyncCommand(Func<Task<TResult>> command)
    {
        _command = command;
    }
...

You're confused about TResult and Task. 您对TResult和Task感到困惑。 As you have already AsyncCommand<TResult> 由于您已经有了AsyncCommand<TResult>

public class AsyncCommand<TResult> : AsyncCommandBase, INotifyPropertyChanged
{
}

A class static AsyncCommand like a factory to create the command 一个像工厂一样的静态AsyncCommand类来创建命令

    public static class AsyncCommand
    {
        public static AsyncCommand<object> Create(Func<Task> command)
        {
            return new AsyncCommand<object>(async () => { await command(); return null; });
        }

        public static AsyncCommand<TResult> Create<TResult>(Func<Task<TResult>> command)
        {
            return new AsyncCommand<TResult>(command);
        }
    }

Next, you create your command by the factory AsyncCommand like this: 接下来,通过工厂AsyncCommand创建命令,如下所示:

public async Task<string> Add()
{
    //you can put whatever you want, in my project, it's string containing the message
    //your stuff
    var Result = Helper.Get(Configuration.Settings);
}

private AsyncCommand<string> _addCommand;
public AsyncCommand<string> AddCommand
        {
            get
            {
                if (_addCommand!= null)
                    return _addCommand;

                _addCommand= AsyncCommand.Create(Add);
                return _addCommand;
            }
        }

XAML XAML

I show the progress bar if the task is in execution 如果任务正在执行,我会显示进度栏

<Grid VerticalAlignment="Center" Visibility="{Binding AddCommand.Execution, Converter={StaticResource NullToVisibilityConverter}}">
                <!--Busy indicator-->
                <ProgressBar HorizontalAlignment="Stretch" Foreground="{Binding AccentBaseColor}" 
                                           Visibility="{Binding AddCommand.Execution.IsNotCompleted,
                             Converter={StaticResource BooleanToVisibilityConverter}}"
                             IsIndeterminate="True"
                             Value="100" />
</Grid>

We believe that this is probably a Semantic model bug. 我们认为这可能是语义模型错误。 Semantic model should be showing a Type of null for all lambda expressions. 对于所有lambda表达式,语义模型都应显示null类型。

You should use dispatcher on calling command. 您应该在调用命令时使用调度程序。

public CarasViewModel()
{
 AddCommand = new ICommand<Task>(() => Add());
}

public ICommand AddCommand { get; private set; }

async Task Add()
{
   Thread longRunningThread = new Thread(new ThreadStart(delegate (){ Thread.Sleep(10000); Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new CalculateTimeElapsed(OnAdd)); }));
longRunningThread.Start();}
void OnAdd{}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM