Вам будет лучше реализовать Асинхронный шаблон на основе событий , чтобы ваша разработка могла отлавливать события на всех различных этапах.
По сути, как бы я сначала создал интерфейс IAsyncCommand следующим образом.
public interface IAsyncCommand<TRequest, TResponse, TCorrelation> : ICommand<TRequest, TResponse>
{
event CommandProgressChangedEventHandler<string, TCorrelation> ProgressChanged;
event CommandCompletedEventHandler<TResponse, TCorrelation> Completed;
bool CancellationPending { get; }
bool IsBusy { get; }
TCorrelation CorrelationId(TRequest request);
void ExecuteAsync(TRequest request);
void ExecuteAsync(TRequest request, CommandCompletedEventHandler<TResponse, TCorrelation> completedCallback, CommandProgressChangedEventHandler<string, TCorrelation> progressCallback);
void CancelAsync();
}
реализуйте эти два CommandProgressChangedEventHander и CommandCompletedEventHandler на основе вашего сценария и заполните Аргумент соответствующим образом.
Если мы предполагаем, что наша ветка должна проверить, является ли конкретный рассматриваемый URL допустимым, код выглядит следующим образом ...
public class UrlCheckCommand : AsyncCommandBase<string, bool, string>, IUrlCheckCommand
{
public override string CorrelationId(string request)
{
return request; //Guid.NewGuid().ToString();
}
public override bool Execute(string request)
{
return CommandHelper.CheckUrlValidity(request);
}
}
Класс AsyncCommandBase - это абстрактный класс, который реализует интерфейс IAsyncCommand.
Скелет для этого класса определен ниже.
public abstract class AsyncCommandBase<TRequest, TResponse, TCorrelation> : IAsyncCommand<TRequest, TResponse, TCorrelation>
{
protected AsyncOperation operation = null;
protected BackgroundWorker worker = null;
#region IAsyncCommand<TRequest,TResponse,TCorrelation> Members
//Implement all the interface members as per your use....
#endregion
protected void worker_DoWork(object sender, DoWorkEventArgs e)
{
e.Result = Execute((TRequest)e.Argument);
}
protected void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
OnProgressChanged(e);
}
protected void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
OnCompleted(e);
}
protected void ReportProgress(int percentageProgress, string message)
{
if (worker != null && worker.WorkerReportsProgress)
worker.ReportProgress(percentageProgress, message);
else
OnProgressChanged(new ProgressChangedEventArgs(percentageProgress, message));
}
protected void OnProgressChanged(ProgressChangedEventArgs e)
{
if (ProgressChanged != null)
{
SendOrPostCallback callback = new SendOrPostCallback(delegate { ProgressChanged(this, new CommandProgressChangedEventArgs<string, TCorrelation>(e.ProgressPercentage, e.UserState as string, (TCorrelation)operation.UserSuppliedState)); });
operation.Post(callback, null);
}
}
protected void OnCompleted(RunWorkerCompletedEventArgs e)
{
if (Completed != null)
{
TResponse response = default(TResponse);
if (e.Error == null)
response = (TResponse)e.Result;
SendOrPostCallback callback = new SendOrPostCallback(delegate { Completed(this, new CommandCompletedEventArgs<TResponse, TCorrelation>(response, e.Error, (TCorrelation)operation.UserSuppliedState, e.Cancelled)); });
operation.PostOperationCompleted(callback, null);
}
}
}
Вы можете заполнить обработчик Progress и Completed Event, и они являются ключом к населению Argument. Вы даже можете использовать его для заполнения процентов прогресса, состояния пользователя и т. Д. *