Windows Workflow 4 - когда отправляются записи отслеживания? - PullRequest
1 голос
/ 15 марта 2011

У меня есть длительное действие (где действие постоянно выполняет работу в течение длительного периода времени - не действие, которое ожидает ответа от внешнего источника), и я хочу сообщить о прогрессе от этой деятельности. Однако я не могу заставить это работать.

У меня есть простое консольное приложение, которое запускает действие:

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] Я предполагаю, что на самом деле задаю более широкий вопрос: когда записи отслеживания генерируются механизмом выполнения рабочего процесса? Мои исследования показывают, что все записи для определенного действия отправляются после действия завершено. Есть ли способ заставить их испускаться во время выполнения действия?

Ответы [ 3 ]

1 голос
/ 28 марта 2011

Я также задал этот вопрос на форуме рабочего процесса MSDN и провел дополнительное расследование самостоятельно, основываясь на полученных там комментариях.В результате я думаю, что записи отслеживания генерируются, когда действие завершается, или добавляются в закладки.См. http://social.msdn.microsoft.com/Forums/en-US/wfprerelease/thread/8ce5dee9-9a19-4445-ad7f-33e181ec228b для получения дополнительной информации.

1 голос
/ 27 июня 2012

Использование AsyncCodeActivity позволило мне принудительно обработать запись отслеживания при запуске действия.

protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
    {
        CustomTrackingRecord customRecord = new CustomTrackingRecord("Start")
        {
            Data =
            {
            {"Date", DateTime.Now.ToShortDateString()},
            }
        };

        context.Track(customRecord);


        var executeDelegate = new Action(FakeWork);
        context.UserState = executeDelegate;
        return executeDelegate.BeginInvoke(callback, state);

    }

    private void FakeWork() {
        // do nothing
        // This allows the CustomTrackingRecord to be handled by the WorkFlowTracker 
        // so that we can identify the start of the activity.
        // The real work is done synchronously in the EndExecute method.
    }

    protected override void EndExecute(AsyncCodeActivityContext context, IAsyncResult result) {

        var executeDelegate = (Action)context.UserState;
        executeDelegate.EndInvoke(result);

        Execute(context);
    }

    protected  void Execute(CodeActivityContext context)
    {
       // Do Work
    }
1 голос
/ 15 марта 2011

Это может быть побочное поведение TrackingParticipant ... Попробуйте НЕ расширять TrackingParticipant и посмотрите, имеет ли это значение.

Расширения рабочих процессов не должны расширять какой-либо базовый класс или реализовывать какой-либо интерфейс. Любой объект может быть расширением.

Я сделал расширения, которые ни от чего не расширяются, и они работают так, как вы ожидаете в течение всего жизненного цикла.

...