DEVKIT1008 - phuocle/Dynamics-Crm-DevKit GitHub Wiki
This analyzer detects usage of parallel execution patterns within IPlugin or CodeActivity classes. Multi-threading and parallel execution are not supported in the Dataverse sandbox and can cause unpredictable behavior, crashes, and data corruption.
📚 Do not use parallel execution within plug-ins and workflow activities
The Dataverse platform does not support multi-threading within plug-ins. Using parallel execution patterns can cause thread-safety issues, unpredictable behavior, and errors that are difficult to diagnose.
When you use parallel execution in plugins:
- Sandbox Restrictions: The sandbox environment doesn't support multi-threading properly
- Thread-Safety Issues: Shared resources may be accessed concurrently, causing race conditions
- Unpredictable Behavior: Threads may be terminated unexpectedly by the platform
- Transaction Problems: Database transactions cannot span multiple threads properly
| Pattern | Example |
|---|---|
Task.Run() |
Task.Run(() => DoWork()); |
Task.Factory.StartNew() |
Task.Factory.StartNew(() => DoWork()); |
Parallel.For() |
Parallel.For(0, 10, i => Process(i)); |
Parallel.ForEach() |
Parallel.ForEach(items, Process); |
Parallel.Invoke() |
Parallel.Invoke(Action1, Action2); |
new Thread() |
new Thread(() => DoWork()).Start(); |
ThreadPool.QueueUserWorkItem() |
ThreadPool.QueueUserWorkItem(DoWork); |
The analyzer flags the following patterns within IPlugin or CodeActivity classes:
-
Task.Run()andTask.Factory.StartNew()method calls -
Parallel.For(),Parallel.ForEach(),Parallel.Invoke()method calls -
new Thread()object creation -
ThreadPool.QueueUserWorkItem()method calls
public class MyPlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
var service = factory.CreateOrganizationService(null);
var entities = GetEntitiesToProcess();
// ❌ Parallel.ForEach is not supported
Parallel.ForEach(entities, entity => {
service.Update(entity);
});
// ❌ Task.Run spawns a new thread
Task.Run(() => ProcessData());
// ❌ Creating threads directly
var thread = new Thread(() => DoBackgroundWork());
thread.Start();
}
}public class MyPlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
var service = factory.CreateOrganizationService(null);
var entities = GetEntitiesToProcess();
// ✓ Process entities sequentially
foreach (var entity in entities)
{
service.Update(entity);
}
// ✓ Direct method call
ProcessData();
}
}- Replace Parallel.ForEach with foreach: Convert parallel loops to sequential loops
- Remove Task.Run calls: Execute the code synchronously instead
- Remove Thread instantiation: Use direct method calls
- Parallel.ForEach(items, item => {
- ProcessItem(item);
- });
+ foreach (var item in items)
+ {
+ ProcessItem(item);
+ }If you have a legitimate need to suppress this warning:
#pragma warning disable DEVKIT1008
Task.Run(() => DoWork());
#pragma warning restore DEVKIT1008Or in .editorconfig:
[*.cs]
dotnet_diagnostic.DEVKIT1008.severity = none| Property | Value |
|---|---|
| Rule ID | DEVKIT1008 |
| Category | DynamicsCrm.DevKit |
| Severity | Error |
| Enabled by default | Yes |