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. 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".
How can I combine async
and void
or, can I do something any better?
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:
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. As you have already AsyncCommand<TResult>
public class AsyncCommand<TResult> : AsyncCommandBase, INotifyPropertyChanged
{
}
A class static AsyncCommand
like a factory to create the command
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:
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
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.
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{}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.