У меня есть длительное действие (где действие постоянно выполняет работу в течение длительного периода времени - не действие, которое ожидает ответа от внешнего источника), и я хочу сообщить о прогрессе от этой деятельности. Однако я не могу заставить это работать.
У меня есть простое консольное приложение, которое запускает действие:
class Program
{
static void Main(string[] args)
{
var wfApp = new WorkflowApplication(new ActivityLibrary.ProgressActivity());
var autoResetEvent = new AutoResetEvent(false);
wfApp.Completed = e => autoResetEvent.Set();
wfApp.Extensions.Add(new ConsoleTrackingParticipant());
wfApp.Run();
autoResetEvent.WaitOne();
Console.WriteLine("Done");
Console.ReadLine();
}
}
internal class ConsoleTrackingParticipant : TrackingParticipant
{
protected override void Track(TrackingRecord record, TimeSpan timeout)
{
Console.WriteLine(record.EventTime.ToString());
}
}
Я пытался реализовать ProgressActivity двумя способами. Сначала я попытался извлечь из CodeActivity, но когда я использую эту реализацию, я получаю все пользовательские записи отслеживания вместе, как только рабочий процесс завершен (хотя записанная запись.EventTime верна):
public sealed class ProgressActivity : CodeActivity
{
protected override void Execute(CodeActivityContext context)
{
for (var i = 0; i <= 10; i++)
{
var customTrackingRecord = new CustomTrackingRecord("ProgressTrackingRecord")
{
Data = { { "Progress", i * 10.0 }}
};
context.Track(customTrackingRecord);
Thread.Sleep(1000);
}
}
}
Затем я попытался наследовать от AsyncCodeActivity, но в этом случае я получаю «ObjectDisposedException: доступ к ActivityContext возможен только в рамках функции, в которую он был передан» в строке context.Track:
public sealed class ProgressActivity : AsyncCodeActivity
{
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
Action action = () =>
{
for (var i = 0; i <= 10; i++)
{
var customTrackingRecord = new CustomTrackingRecord("ProgressTrackingRecord")
{
Data = { { "Progress", i * 10.0 } }
};
context.Track(customTrackingRecord);
Thread.Sleep(1000);
}
};
context.UserState = action;
return action.BeginInvoke(callback, state);
}
protected override void EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
{
((Action)context.UserState).EndInvoke(result);
}
}
Может кто-нибудь объяснить, где я ошибся?
P.S. Я понимаю, что подход, который я показал, не будет хорошо масштабироваться, если рабочий процесс когда-либо будет выполняться на сервере, но приложение, которое я создаю, является настольным приложением.
[EDIT]
Я предполагаю, что на самом деле задаю более широкий вопрос: когда записи отслеживания генерируются механизмом выполнения рабочего процесса? Мои исследования показывают, что все записи для определенного действия отправляются после действия завершено. Есть ли способ заставить их испускаться во время выполнения действия?