JoinableTaskContext Class

Definition

A common context within which joinable tasks may be created and interact to avoid deadlocks.

public ref class JoinableTaskContext : IDisposable, Microsoft::VisualStudio::Threading::IHangReportContributor
public class JoinableTaskContext : IDisposable, Microsoft.VisualStudio.Threading.IHangReportContributor
type JoinableTaskContext = class
    interface IHangReportContributor
    interface IDisposable
Public Class JoinableTaskContext
Implements IDisposable, IHangReportContributor
Inheritance
JoinableTaskContext
Implements

Remarks

There are three rules that should be strictly followed when using or interacting with JoinableTasks: 1. If a method has certain thread apartment requirements (STA or MTA) it must either: a) Have an asynchronous signature, and asynchronously marshal to the appropriate thread if it isn't originally invoked on a compatible thread. The recommended way to switch to the main thread is:

await JoinableTaskFactory.SwitchToMainThreadAsync();

b) Have a synchronous signature, and throw an exception when called on the wrong thread. In particular, no method is allowed to synchronously marshal work to another thread (blocking while that work is done). Synchronous blocks in general are to be avoided whenever possible. 2. When an implementation of an already-shipped public API must call asynchronous code and block for its completion, it must do so by following this simple pattern:

JoinableTaskFactory.Run(async delegate {
    await SomeOperationAsync(...);
});
  1. If ever awaiting work that was started earlier, that work must be Joined. For example, one service kicks off some asynchronous work that may later become synchronously blocking:
JoinableTask longRunningAsyncWork = JoinableTaskFactory.RunAsync(async delegate {
    await SomeOperationAsync(...);
});

Then later that async work becomes blocking:

longRunningAsyncWork.Join();

or perhaps:

await longRunningAsyncWork;

Note however that this extra step is not necessary when awaiting is done immediately after kicking off an asynchronous operation.

Constructors

JoinableTaskContext()

Initializes a new instance of the JoinableTaskContext class assuming the current thread is the main thread and Current will provide the means to switch to the main thread from another thread.

JoinableTaskContext(Thread, SynchronizationContext)

Initializes a new instance of the JoinableTaskContext class.

Properties

Factory

Gets the factory which creates joinable tasks that do not belong to a joinable task collection.

IsOnMainThread

Gets a value indicating whether the caller is executing on the main thread.

IsWithinJoinableTask

Gets a value indicating whether the caller is currently running within the context of a joinable task.

MainThread

Gets the main thread that can be shared by tasks created by this context.

NoMessagePumpSynchronizationContext

Gets a SynchronizationContext which, when applied, suppresses any message pump that may run during synchronous blocks of the calling thread.

Methods

Capture()

Captures the caller's context and serializes it as a string that is suitable for application via a subsequent call to RunAsync(Func<Task>, String, JoinableTaskCreationOptions).

CreateCollection()

Creates a collection for in-flight joinable tasks.

CreateDefaultFactory()

Creates a factory without a JoinableTaskCollection.

CreateFactory(JoinableTaskCollection)

Creates a joinable task factory that automatically adds all created tasks to a collection that can be jointly joined.

Dispose()

Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.

Dispose(Boolean)

Disposes managed and unmanaged resources held by this instance.

GetHangReport()

Contributes data for a hang report.

IsMainThreadBlocked()

Gets a value indicating whether the main thread is blocked for the caller's completion.

IsMainThreadMaybeBlocked()

Gets a very likely value whether the main thread is blocked for the caller's completion. It is less accurate when the UI thread blocking task just starts and hasn't been blocked yet, or the dependency chain is just removed. However, unlike IsMainThreadBlocked(), this implementation is lock free, and faster in high contention scenarios.

OnFalseHangDetected(TimeSpan, Guid)

Invoked when an earlier hang report is false alarm.

OnHangDetected(TimeSpan, Int32, Guid)

Invoked when a hang is suspected to have occurred involving the main thread.

SuppressRelevance()

Conceals any JoinableTask the caller is associated with until the returned value is disposed.

Explicit Interface Implementations

IHangReportContributor.GetHangReport()

Contributes data for a hang report.

Applies to

Thread Safety

This type is thread-safe for all members.