System.InvalidOperationException: Activation access violation. A non-activation thread attempted to access activation services. #9196
Replies: 3 comments
-
I have fixed it as above. But if i want to use multi-thread, how should I do. I'm not clear why Parallel can not use |
Beta Was this translation helpful? Give feedback.
-
Here is one approach you can take: var listStatus = state.State;
var tasks = new Dictionary<string, Task<ProductDetails>>(listStatus.Count);
// Start multiple tasks concurrently, not waiting for them to complete.
foreach (var id in listStatus)
{
var productGrain = GrainFactory.GetGrain<IProductGrain>(id);
tasks[id] = productGrain.GetProductDetailsAsync();
}
// Wait for the tasks to complete.
await Task.WhenAll(tasks.Values);
// Proces the results
foreach (var id in listStatus)
{
_productCache[id] = await tasks[id];
} This gives you concurrency: your grain issues overlapping requests to other grains. Each grain is effectively single-threaded, however, so it does not give you parallelism. The distinction between parallelism and concurrency is subtle. Parallelism requires multi-threading, where concurrency can interleave tasks on a single thread. Parallelism is not allowed in grains by default: we try to prevent it because it can lead to data races. Concurrency is allowed. The above example code gives you concurrency. The You can jump the guardrail quite easily if you want to by capturing a reference to var grainFactory = GrainFactory; // NOTE: capture the grain factory while still on the grain's context.
await Parallel.ForEachAsync(
state.State,
async (id, _) =>
{
// IMPORTANT: DO NOT ACCESS PRIVATE GRAIN MEMBERS HERE
// NOTE: 'grainFactory' not 'GrainFactory'
var productGrain = grainFactory.GetGrain<IProductGrain>(id);
_productCache[id] = await productGrain.GetProductDetailsAsync();
}); In the above example, since you are calling the product grain from outside of the grain's context, distributed tracing would show NOT show that the call is coming from your inventory grain. It would come from the 'hosted client' instead. Hope that helps. |
Beta Was this translation helpful? Give feedback.
-
Thanks a lot
原始邮件
发件人:"Reuben Bond"< ***@***.*** >;
发件时间:2024/10/21 23:31
收件人:"dotnet/orleans"< ***@***.*** >;
抄送人:"BurningTeng"< ***@***.*** >;"Author"< ***@***.*** >;
主题:Re: [dotnet/orleans] System.InvalidOperationException: Activationaccess violation. A non-activation thread attempted to access activationservices. (Discussion #9196)
Here is one approach you can take:
var tasks = new Dictionary<string, Task<ProductDetails>>(); foreach (var id in list_status) { var productGrain = GrainFactory.GetGrain<IProductGrain>(id); tasks[id] = productGrain.GetProductDetailsAsync(); } await Task.WhenAll(tasks.Values); foreach (var id in list_status) { _productCache[id] = await tasks[id]; }
This gives you concurrency: your grain issues overlapping requests to other grains. Each grain is effectively single-threaded, however.
You can achieve this another way, too, using Parallel.ForEachAsync if you'd like. You just have to capture a reference to IGrainFactory in the grain's context. The Grain.GrainFactory property throws when you try to access it externally to act as a guardrail: if you are accessing one part of a grain from another thread, you can access other parts eg internal state, and that would be a violation of single-threadedness.
Here's that alternative:
var list_status = state.State; var grainFactory = GrainFactory; foreach (var id in list_status) { var productGrain = grainFactory.GetGrain<IProductGrain>(id); _productCache[id] = await productGrain.GetProductDetailsAsync(); }
Hope that helps
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
Code as above, it seems Parallel.ForEachAsync is errors for InventoryGrain. Why Parallel cause the error and how to fix it.
Beta Was this translation helpful? Give feedback.
All reactions