C#Task.WhenAll不会触发下一个任务

时间:2015-12-08 20:41:52

标签: c# multithreading

我是多任务的新手,但是我试图了解它是如何运作的。我有以下代码,我认为这将创建一个任务并运行performInitialLoad方法,当完成后,将触发initializeDataHarvester方法。 performInitialLoad工作正常,它确实到达方法的底部,因为我可以看到文本"初始标签数据加载完成"在我的控制台中。但它似乎永远不会触发initializeDataHarvester方法。有什么想法吗?

   java.lang.SecurityException: setContextClassLoader
                at sun.misc.InnocuousThread.setContextClassLoader(InnocuousThread.java:64)
                at org.vertx.java.core.impl.DefaultContext.setTCCL(DefaultContext.java:63)
                at org.vertx.java.core.impl.DefaultVertx.setContext(DefaultVertx.java:325)
                at org.vertx.java.core.eventbus.impl.DefaultEventBus.sendOrPub(DefaultEventBus.java:743)
                at org.vertx.java.core.eventbus.impl.DefaultEventBus.sendOrPub(DefaultEventBus.java:670)
                at org.vertx.java.core.eventbus.impl.DefaultEventBus.sendReply(DefaultEventBus.java:528)
                at org.vertx.java.core.eventbus.impl.BaseMessage.sendReply(BaseMessage.java:348)
                at org.vertx.java.core.eventbus.impl.BaseMessage.reply(BaseMessage.java:156)
                at org.vertx.java.core.eventbus.impl.BaseMessage.reply(BaseMessage.java:76)
                .........................
                at rx.Observable$32.onNext(Observable.java:7187)
                at rx.observers.SafeSubscriber.onNext(SafeSubscriber.java:130)
                at rx.internal.operators.OperatorSubscribeOn$1$1$1.onNext(OperatorSubscribeOn.java:76)
                at rx.internal.operators.OperatorMerge$InnerSubscriber.emit(OperatorMerge.java:620)
                at rx.internal.operators.OperatorMerge$InnerSubscriber.onNext(OperatorMerge.java:545)
                at rx.internal.operators.OperatorMerge$InnerSubscriber.emit(OperatorMerge.java:635)
                at rx.internal.operators.OperatorMerge$InnerSubscriber.onNext(OperatorMerge.java:545)
                at rx.internal.operators.OperatorMerge$InnerSubscriber.emit(OperatorMerge.java:635)
                at rx.internal.operators.OperatorMerge$InnerSubscriber.onNext(OperatorMerge.java:545)
                at rx.internal.operators.OperatorMap$1.onNext(OperatorMap.java:54)
                ...................
                at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:53)
                at com.mongodb.async.client.MongoClientImpl$2$2.onResult(MongoClientImpl.java:144)
                at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:53)
                at com.mongodb.operation.OperationHelper$ConnectionReleasingWrappedCallback.onResult(OperationHelper.java:140)
                at com.mongodb.operation.MixedBulkWriteOperation$3.onResult(MixedBulkWriteOperation.java:208)
                at com.mongodb.operation.MixedBulkWriteOperation$3.onResult(MixedBulkWriteOperation.java:187)
                at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:53)
                at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor$1.onResult(DefaultServer.java:171)
                at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:53)
                at com.mongodb.connection.InsertCommandProtocol$1.onResult(InsertCommandProtocol.java:86)
                at com.mongodb.connection.InsertCommandProtocol$1.onResult(InsertCommandProtocol.java:79)
                at com.mongodb.connection.WriteCommandProtocol.executeBatchesAsync(WriteCommandProtocol.java:154)
                at com.mongodb.connection.WriteCommandProtocol.access$000(WriteCommandProtocol.java:37)
                at com.mongodb.connection.WriteCommandProtocol$1.onResult(WriteCommandProtocol.java:145)
                at com.mongodb.connection.WriteCommandProtocol$1.onResult(WriteCommandProtocol.java:123)
                at com.mongodb.connection.CommandResultCallback.callCallback(CommandResultCallback.java:54)
                at com.mongodb.connection.CommandResultCallback.callCallback(CommandResultCallback.java:29)
                at com.mongodb.connection.CommandResultBaseCallback.callCallback(CommandResultBaseCallback.java:39)

1 个答案:

答案 0 :(得分:4)

Task.WhenAll会立即返回 - 但会返回任务,该任务将在任务完成时完成。你现在忽略了那个回报值。你也没有开始调用WhenAll的任务,这就是为什么这个任务永远不会完成的原因。

你可以使用:

Task.WhenAll(initialLoad).ContinueWith(...);

...但更好的是,你可以完全避免使用WhenAll,因为你无论如何都只有一个任务。

您还应该:

  • 了解async / await,这会让更多更容易
  • 开始遵循.NET命名约定

使用async / await,此代码将类似于:

private async Task MainTaskLoader()
{
    await Task.Run(PerformInitialTagLoad);
    InitializeDataHarvester();
}

如果您真的要运行多项内容,可以使用:

private async Task MainTaskLoader()
{
    var task1 = Task.Run(PerformInitialTagLoad);
    var task2 = Task.Run(SomethingElse);
    // Imagine we have many of these...
    await Task.WhenAll(task1, task2);
    InitializeDataHarvester();
}

理想情况下,您也可以使PerformInitialTagLoad成为异步方法,请注意 - 这也需要使插入异步。