-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider running on the UI thread by default #8
Comments
My main concern with making, There is now a requirement to use: [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
[ProvideAutoLoad(Constants.vsContextNoSolution, PackageAutoLoadFlags.BackgroundLoad)] This means that initialization is sometimes done the UI thread (when package load is triggered by a command) and sometimes on a background thread (when package load is triggered by a context). I've had plenty of situations where my my extension has sometimes worked and sometimes not worked depending on initialization order. For this reason, I'd maybe prefer the default to be the situation that is less likely to work (running on a background thread). This would force me to be explicit when a test or some library code requires the UI thread. Perhaps the most common scenario would be testing the creation of MEF components on a background thread (and initializing asynchronously where they're do any initialization that requires the UI thread). I'd prefer being able to do the following: [VsFact]
public void MyComponent()
{
var componentModel = (IComponentModel)(await GetServiceAsync(typeof(SComponentModel)));
var exports = componentModel.DefaultExportProvider;
var myComponent = exports.GetExportedValue<MyComponent>();
await myComponent.InitializeAsync();
} ...without having to remember to do Does that make sense? |
@jcansdale If the (The hoops required is the test must execute in a fresh VS instance to guarantee that the type is not already initialized. For a test with a focus on specific initialization conditions, explicitly stating the thread affinity is a valuable clarification regardless of what the default is.) |
It was a bit of a rushed example. You're right it wouldn't work consistently in its current form. With Here is a more realistic example: [VsFact(UIThread = false)]
public async Task TestMyComponentAsync()
{
var componentModel = (IComponentModel)await AsyncServiceProvider.GlobalProvider.GetServiceAsync(typeof(SComponentModel));
var catalog = new TypeCatalog(typeof(MyService));
var container = new CompositionContainer(catalog, componentModel.DefaultExportProvider);
var service = container.GetExportedValue<MyService>();
await service.InitializeAsync();
Assert.NotNull(service);
} Alternatively you could do: [VsFact(UIThread = true)]
public async Task TestMyComponentAsync()
{
var componentModel = (IComponentModel)await AsyncServiceProvider.GlobalProvider.GetServiceAsync(typeof(SComponentModel));
var catalog = new TypeCatalog(typeof(MyService));
var container = new CompositionContainer(catalog, componentModel.DefaultExportProvider);
await TaskScheduler.Default;
var service = container.GetExportedValue<MyService>();
await service.InitializeAsync();
Assert.NotNull(service);
} I do find Unfortunately the first example doesn't work on Visual Studio 2017 because Whether the default is Re: what the default should be , I'm leaning slightly towards Here's an example PR that I would have liked to test like this, but we tested using some rather convoluted manual testing: github/VisualStudio#1689 |
Currently the library starts tests on background threads by default. The behavior can be changed for an assembly by the following:
I would propose running tests on the UI thread by default instead, using one of the following:
UIThread
to true, orUIThread
property, and force the value was trueOverall, I believe this change better represents the requirements of code users are planning to execute as integration tests.
This change would impact users in the following ways:
IAsyncLifetime
interface can be used to implement asynchronous initialization and cleanup code, since the UI thread will be blocked for the execution of constructors andDispose
await TaskScheduler.Default
to switch to a background threadThe text was updated successfully, but these errors were encountered: