没有活动的ActorContext,这很可能是由于在此actor

时间:2017-09-15 11:53:27

标签: c# async-await akka akka.net

我有一个问题,我不太清楚如何解决这个问题,除了让我的Akka Actor没有异步方法。

这是我的演员代码:

public class AggregatorActor : ActorBase, IWithUnboundedStash
{
    public IStash Stash { get; set; }

    private AggregatorTimer _aggregatorTimer;
    private IActorSystemSettings _settings;

    private AccountSummary _accountResponse;
    private ContactDetails _contactResponse;
    private AnalyticDetails _analyticsResponse;
    private FinancialDetails _financialResponse;

    private ActorSelection _accountActor;
    private ActorSelection _contactActor;
    private ActorSelection _analyticsActor;
    private ActorSelection _financialActor;

    public AggregatorActor(IActorSystemSettings settings) : base(settings)
    {
        _accountActor = Context.System.ActorSelection(ActorPaths.AccountActorPath);
        _contactActor = Context.System.ActorSelection(ActorPaths.ContactActorPath);
        _analyticsActor = Context.System.ActorSelection(ActorPaths.AnalyticsActorPath);
        _financialActor = Context.System.ActorSelection(ActorPaths.FinancialActorPath);

        _settings = settings;
    }

    #region Public Methods

    public override void Listening()
    {
        ReceiveAsync<ProfilerMessages.ProfilerBase>(async x => await HandleMessageAsync(x));
    }
    private void Busy()
    {
        Receive<ProfilerMessages.ProfilerBase>(x => Stash.Stash());
    }

    private void Aggregate()
    {
        try
        {
            Context.Sender.Tell(AggregatedSummaryResponse.Instance(_accountResponse, _contactResponse, _analyticsResponse, _financialResponse));
        }
        catch (Exception ex)
        {
            ExceptionHandler(ex);
        }
    }

    public override async Task HandleMessageAsync(object msg)
    {
        //if is summary, generate new isntance of AggregatorTimer in _eventHandlerCollection.
        if (msg is ProfilerMessages.GetSummary)
        {
            //Become busy. Stash
            Become(Busy);

            //Handle different requests
            var clientId = (msg as ProfilerMessages.GetSummary).ClientId;
            await HandleSummaryRequest(clientId);
        }
    }
    private async Task HandleSummaryRequest(string clientId)
    {
        try
        {
            var accountMsg = new AccountMessages.GetAggregatedData(clientId);
            _accountResponse = (await _accountActor.Ask<Messages.AccountMessages.AccountResponseAll>(accountMsg, TimeSpan.FromSeconds(_settings.NumberOfSecondsToWaitForResponse))).AccountDetails;

            //Need to uncomment this
            var contactMsg = new ContactMessages.GetAggregatedContactDetails(clientId);
            _contactResponse = (await _contactActor.Ask<Messages.ContactMessages.ContactResponse>(contactMsg, TimeSpan.FromSeconds(_settings.NumberOfSecondsToWaitForResponse))).ContactDetails;

            var analyticMsg = new AnalyticsMessages.GetAggregatedAnalytics(clientId);
            _analyticsResponse = (await _analyticsActor.Ask<Messages.AnalyticsMessages.AnalyticsResponse>(analyticMsg, TimeSpan.FromSeconds(_settings.NumberOfSecondsToWaitForResponse))).AnalyticDetails;

            var financialMsg = new FinancialMessages.GetAggregatedFinancialDetails(clientId);
            _financialResponse = (await _financialActor.Ask<Messages.FinancialMessages.FinancialResponse>(financialMsg, TimeSpan.FromSeconds(_settings.NumberOfSecondsToWaitForResponse))).FinancialDetails;

            //Start new timer
            _aggregatorTimer = new AggregatorTimer(_settings.NumberOfSecondsToWaitForResponse);
            _aggregatorTimer.TimeElapsed += _aggregatorTimer_TimeElapsed;
        }
        catch (Exception ex)
        {
            ExceptionHandler(ex);
        }
    }
    //Event that is raised when an external timers time elapsed.
    private async void _aggregatorTimer_TimeElapsed(object sender, ElapsedTimeHandlerArg e)
    {
        Aggregate();

        _aggregatorTimer = null;

        _accountResponse = null;
        _contactResponse = null;
        _analyticsResponse = null;
        _financialResponse = null;

        //Unstash
        Stash.Unstash();

        //Start listening again
        Become(Listening);
    }

    #endregion
}

_aggregatorTimer_TimeElapsed事件中,我调用了await Aggregate函数,但抛出了以下异常。

  

没有活跃的ActorContext,这很可能是由于在此actor中使用了异步操作

我认为这是因为聚合函数尝试Tell()关于汇总的响应的Sender,但那些Tasks尚未完成?我可能完全错了,但我不知道为什么抛出它。

1 个答案:

答案 0 :(得分:1)

我不确定你甚至需要一个AggregatorTimer - 在akka中你有一个Context.System.Scheduler对象,它可以用来安排将来发生的事件。

另一件事是你可能不应该在事件处理程序中执行逻辑。如果你真的需要在你的代码中使用它们,那么一旦事件被触发,最好只限制它们发送消息,即:

Receive<TimedOut>(_ => /* handle timeout message */);

var self = Self; // bind current self to a variable, so it won't change
_aggregatorTimer.TimeElapsed += (sender, e) => self.Tell(new TimedOut(), self);