Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8464f8e
Fixed dispatcher for Xaml Islands. leveraging DispatcherQueueHelper i…
azchohfi Mar 31, 2020
beafb0a
Changed all dispatcher queue fields to properties, so they can be set…
azchohfi Mar 31, 2020
d3a85db
Small fix on TitleBarExtensions.GetTitleBar for Xaml Islands.
azchohfi Apr 1, 2020
edfb11e
Merge branch 'dev/7.0.0' into xamlIslandsFixes
azchohfi Apr 2, 2020
8b9a3ba
Merge branch 'dev/7.0.0' into xamlIslandsFixes
azchohfi Apr 2, 2020
8f81e73
Xaml Islands Tests now work properly with UIThread.
azchohfi Apr 3, 2020
c2627ae
More Xaml Islands updates for flyouts, popups.
azchohfi Apr 4, 2020
9362358
Fixed Xaml Islands Tests.
azchohfi Apr 4, 2020
0d335b7
Removed compilation of Xaml Islands Projects on release mode.
azchohfi Apr 4, 2020
9d02ad8
Updated .Net Native.
azchohfi Apr 5, 2020
572f1c5
Small fix for Xaml Islands tests on debug builds for unpackaged scena…
azchohfi Apr 6, 2020
e76b247
Added more Xaml Islands tests.
azchohfi Apr 6, 2020
3dd889e
Fixes for x64 Xaml Islands tests.
azchohfi Apr 7, 2020
919df39
Small fixes/improvements for Eyedropper.
azchohfi Apr 8, 2020
74b7c12
Small refactor on DataGrid.
azchohfi Apr 8, 2020
92f8328
Fixes/checks for XamlRoot downlevel.
azchohfi Apr 8, 2020
d2ea666
Small fix for IsXamlRootAvailable.
azchohfi Apr 8, 2020
4789686
Temporarily ignoring DispatcherQueueHelper tests until .Net Native is…
azchohfi Apr 8, 2020
a093bfd
Fixes for Xaml Islands tests.
azchohfi Apr 8, 2020
7752b11
Improved docs for StringExtensions' UIContext param.
azchohfi Apr 9, 2020
142446b
Added small commet to internal abstractions used by Unit Tests.
azchohfi Apr 9, 2020
24d1b5c
Updated dispatcher helper sample to use DispatcherQueueHelper.
azchohfi Apr 9, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@
</When>
</Choose>

<Choose>
<When Condition="'$(Configuration)' == 'Debug' and '$(IsDesignProject)' != 'true'">
<!-- Debug builds have this turned on by default, but it breaks our Xaml Islands Scenarios -->
<PropertyGroup>
<EnableTypeInfoReflection>false</EnableTypeInfoReflection>
<EnableXBindDiagnostics>false</EnableXBindDiagnostics>
</PropertyGroup>
</When>
</Choose>

<Choose>
<When Condition="'$(IsTestProject)' != 'true' and '$(SourceLinkEnabled)' != 'false' and '$(IsSampleProject)' != 'true' and '$(IsDesignProject)' != 'true'">
<PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion GazeInputTest/GazeInputTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
<Version>6.2.9</Version>
<Version>6.2.10</Version>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers">
<Version>1.0.2</Version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Windows.ApplicationModel.Core;
using Microsoft.Toolkit.Uwp.Helpers;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Devices.Enumeration;
using Windows.Foundation.Metadata;
using Windows.UI.Core;
using Windows.System;

namespace Microsoft.Toolkit.Uwp.Connectivity
{
Expand Down Expand Up @@ -59,11 +59,19 @@ public class BluetoothLEHelper
/// </summary>
private BluetoothAdapter _adapter;

/// <summary>
/// Gets or sets which DispatcherQueue is used to dispatch UI updates.
/// </summary>
public DispatcherQueue DispatcherQueue { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this need to be public?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We didn't have the requirement that this class needed to be instantiated from a UI thread. Since this might be a scenario for some users, I wanted to make sure that they could set the dispatcher if they already have an instance of it (thru the ctor), or change it later (thru the public property).


/// <summary>
/// Prevents a default instance of the <see cref="BluetoothLEHelper" /> class from being created.
/// </summary>
private BluetoothLEHelper()
/// <param name="dispatcherQueue">The DispatcherQueue that should be used to dispatch UI updates, or null if this is being called from the UI thread.</param>
private BluetoothLEHelper(DispatcherQueue dispatcherQueue = null)
{
DispatcherQueue = dispatcherQueue ?? DispatcherQueue.GetForCurrentThread();

#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
Init();
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
Expand Down Expand Up @@ -201,8 +209,7 @@ private async Task Init()
/// <param name="args">The advertisement.</param>
private async void AdvertisementWatcher_Received(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args)
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
await DispatcherQueue.ExecuteOnUIThreadAsync(
() =>
{
if (_readerWriterLockSlim.TryEnterReadLock(TimeSpan.FromSeconds(1)))
Expand All @@ -217,7 +224,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(

_readerWriterLockSlim.ExitReadLock();
}
});
}, DispatcherQueuePriority.Normal);
}

/// <summary>
Expand Down Expand Up @@ -286,19 +293,20 @@ private async void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformation
// Protect against race condition if the task runs after the app stopped the deviceWatcher.
if (sender == _deviceWatcher)
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
if (_readerWriterLockSlim.TryEnterWriteLock(TimeSpan.FromSeconds(1)))
await DispatcherQueue.ExecuteOnUIThreadAsync(
() =>
{
var device = BluetoothLeDevices.FirstOrDefault(i => i.DeviceInfo.Id == deviceInfoUpdate.Id);
BluetoothLeDevices.Remove(device);
if (_readerWriterLockSlim.TryEnterWriteLock(TimeSpan.FromSeconds(1)))
{
var device = BluetoothLeDevices.FirstOrDefault(i => i.DeviceInfo.Id == deviceInfoUpdate.Id);
BluetoothLeDevices.Remove(device);

var unusedDevice = _unusedDevices.FirstOrDefault(i => i.Id == deviceInfoUpdate.Id);
_unusedDevices?.Remove(unusedDevice);
var unusedDevice = _unusedDevices.FirstOrDefault(i => i.Id == deviceInfoUpdate.Id);
_unusedDevices?.Remove(unusedDevice);

_readerWriterLockSlim.ExitWriteLock();
}
});
_readerWriterLockSlim.ExitWriteLock();
}
}, DispatcherQueuePriority.Normal);
}
}

Expand Down Expand Up @@ -327,16 +335,15 @@ private async Task AddDeviceToList(DeviceInformation deviceInfo)
// Make sure device name isn't blank or already present in the list.
if (!string.IsNullOrEmpty(deviceInfo?.Name))
{
var device = new ObservableBluetoothLEDevice(deviceInfo);
var device = new ObservableBluetoothLEDevice(deviceInfo, DispatcherQueue);
var connectable = (device.DeviceInfo.Properties.Keys.Contains("System.Devices.Aep.Bluetooth.Le.IsConnectable") &&
(bool)device.DeviceInfo.Properties["System.Devices.Aep.Bluetooth.Le.IsConnectable"]) ||
(device.DeviceInfo.Properties.Keys.Contains("System.Devices.Aep.IsConnected") &&
(bool)device.DeviceInfo.Properties["System.Devices.Aep.IsConnected"]);

if (connectable)
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
await DispatcherQueue.ExecuteOnUIThreadAsync(
() =>
{
if (_readerWriterLockSlim.TryEnterWriteLock(TimeSpan.FromSeconds(1)))
Expand All @@ -348,7 +355,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(

_readerWriterLockSlim.ExitWriteLock();
}
});
}, DispatcherQueuePriority.Normal);

return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Windows.ApplicationModel.Core;
using Microsoft.Toolkit.Uwp.Helpers;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Enumeration;
using Windows.System;
using Windows.UI.Core;
using Windows.UI.Xaml.Media.Imaging;

Expand Down Expand Up @@ -134,17 +135,25 @@ public int Compare(object x, object y)
private ObservableCollection<ObservableGattDeviceService> _services =
new ObservableCollection<ObservableGattDeviceService>();

/// <summary>
/// Gets or sets which DispatcherQueue is used to dispatch UI updates.
/// </summary>
public DispatcherQueue DispatcherQueue { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this need to be public?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We didn't have the requirement that this class needed to be instantiated from a UI thread. Since this might be a scenario for some users, I wanted to make sure that they could set the dispatcher if they already have an instance of it (thru the ctor), or change it later (thru the public property).


/// <summary>
/// Initializes a new instance of the <see cref="ObservableBluetoothLEDevice"/> class.
/// </summary>
/// <param name="deviceInfo">The device information.</param>
public ObservableBluetoothLEDevice(DeviceInformation deviceInfo)
/// <param name="dispatcherQueue">The DispatcherQueue that should be used to dispatch UI updates for this BluetoothLE Device, or null if this is being called from the UI thread.</param>
public ObservableBluetoothLEDevice(DeviceInformation deviceInfo, DispatcherQueue dispatcherQueue = null)
{
DeviceInfo = deviceInfo;
Name = DeviceInfo.Name;

IsPaired = DeviceInfo.Pairing.IsPaired;

DispatcherQueue = dispatcherQueue ?? DispatcherQueue.GetForCurrentThread();

LoadGlyph();

this.PropertyChanged += ObservableBluetoothLEDevice_PropertyChanged;
Expand Down Expand Up @@ -395,7 +404,8 @@ private void ObservableBluetoothLEDevice_PropertyChanged(object sender, Property
/// <exception cref="Exception">Thorws Exception when no permission to access device</exception>
public async Task ConnectAsync()
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
await DispatcherQueue.ExecuteOnUIThreadAsync(
async () =>
{
if (BluetoothLEDevice == null)
{
Expand Down Expand Up @@ -442,7 +452,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio
throw new Exception(_result.ProtocolError.GetErrorString());
}
}
});
}, DispatcherQueuePriority.Normal);
}

/// <summary>
Expand All @@ -468,8 +478,7 @@ public async Task DoInAppPairingAsync()
/// <returns>The task of the update.</returns>
public async Task UpdateAsync(DeviceInformationUpdate deviceUpdate)
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
await DispatcherQueue.ExecuteOnUIThreadAsync(
() =>
{
DeviceInfo.Update(deviceUpdate);
Expand All @@ -479,7 +488,7 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(

LoadGlyph();
OnPropertyChanged("DeviceInfo");
});
}, DispatcherQueuePriority.Normal);
}

/// <summary>
Expand Down Expand Up @@ -512,9 +521,7 @@ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName
/// <param name="args">The arguments.</param>
private async void BluetoothLEDevice_NameChanged(BluetoothLEDevice sender, object args)
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
() => { Name = BluetoothLEDevice.Name; });
await DispatcherQueue.ExecuteOnUIThreadAsync(() => { Name = BluetoothLEDevice.Name; }, DispatcherQueuePriority.Normal);
}

/// <summary>
Expand All @@ -524,29 +531,27 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
/// <param name="args">The arguments.</param>
private async void BluetoothLEDevice_ConnectionStatusChanged(BluetoothLEDevice sender, object args)
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
await DispatcherQueue.ExecuteOnUIThreadAsync(
() =>
{
IsPaired = DeviceInfo.Pairing.IsPaired;
IsConnected = BluetoothLEDevice.ConnectionStatus == BluetoothConnectionStatus.Connected;
});
}, DispatcherQueuePriority.Normal);
}

/// <summary>
/// Load the glyph for this device
/// </summary>
private async void LoadGlyph()
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
await DispatcherQueue.ExecuteOnUIThreadAsync(
async () =>
{
var deviceThumbnail = await DeviceInfo.GetGlyphThumbnailAsync();
var glyphBitmapImage = new BitmapImage();
await glyphBitmapImage.SetSourceAsync(deviceThumbnail);
Glyph = glyphBitmapImage;
});
}, DispatcherQueuePriority.Normal);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Microsoft.Toolkit.Uwp.Helpers;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Security.Cryptography;
using Windows.Storage.Streams;
using Windows.System;

namespace Microsoft.Toolkit.Uwp.Connectivity
{
Expand Down Expand Up @@ -110,13 +112,21 @@ public enum DisplayTypes
/// </summary>
private string _value;

/// <summary>
/// Gets or sets which DispatcherQueue is used to dispatch UI updates.
/// </summary>
public DispatcherQueue DispatcherQueue { get; set; }

/// <summary>
/// Initializes a new instance of the <see cref="ObservableGattCharacteristics"/> class.
/// </summary>
/// <param name="characteristic">The characteristic.</param>
/// <param name="parent">The parent.</param>
public ObservableGattCharacteristics(GattCharacteristic characteristic, ObservableGattDeviceService parent)
/// <param name="dispatcherQueue">The DispatcherQueue that should be used to dispatch UI updates, or null if this is being called from the UI thread.</param>
public ObservableGattCharacteristics(GattCharacteristic characteristic, ObservableGattDeviceService parent, DispatcherQueue dispatcherQueue = null)
{
DispatcherQueue = dispatcherQueue ?? DispatcherQueue.GetForCurrentThread();

Characteristic = characteristic;
Parent = parent;
Name = GattUuidsService.ConvertUuidToName(Characteristic.Uuid);
Expand Down Expand Up @@ -459,9 +469,7 @@ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName
/// <param name="args">The <see cref="GattValueChangedEventArgs"/> instance containing the event data.</param>
private async void Characteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
{
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.Normal,
() => { SetValue(args.CharacteristicValue); });
await DispatcherQueue.ExecuteOnUIThreadAsync(() => { SetValue(args.CharacteristicValue); }, DispatcherQueuePriority.Normal);
}

/// <summary>
Expand Down
12 changes: 8 additions & 4 deletions Microsoft.Toolkit.Uwp.SampleApp/Controls/CodeRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,14 @@ protected override void OnApplyTemplate()

private void RenderDocument()
{
_codeView?.Blocks?.Clear();
_formatter = new RichTextBlockFormatter(_theme);
_formatter.FormatRichTextBlock(_displayedText, _language, _codeView);
_rendered = true;
if (_codeView != null)
{
_codeView.Blocks?.Clear();
_formatter = new RichTextBlockFormatter(_theme);

_formatter.FormatRichTextBlock(_displayedText, _language, _codeView);
_rendered = true;
}
}

private void CopyButton_Click(object sender, RoutedEventArgs e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
<Version>6.2.9</Version>
<Version>6.2.10</Version>
</PackageReference>
<PackageReference Include="Microsoft.Services.Store.Engagement">
<Version>10.1901.28001</Version>
Expand Down Expand Up @@ -292,7 +292,7 @@
<Content Include="SamplePages\CameraHelper\CameraHelper.png" />
<Content Include="SamplePages\Connected Animations\ConnectedAnimations.png" />
<Content Include="SamplePages\DataGrid\DataGrid.png" />
<Content Include="SamplePages\DispatcherHelper\DispatchHelper.png" />
<Content Include="SamplePages\DispatcherQueueHelper\DispatchQueueHelper.png" />
<Content Include="SamplePages\DockPanel\DockPanel.png" />
<Content Include="SamplePages\Facebook Service\FacebookLogo.png" />
<Content Include="SamplePages\LoginButton\LoginButton.png" />
Expand Down Expand Up @@ -456,7 +456,7 @@
<Content Include="SamplePages\InAppNotification\InAppNotificationXaml.bind" />
<Content Include="SamplePages\ListViewExtensions\ListViewExtensionsCode.bind" />
<Content Include="SamplePages\Implicit Animations\ImplicitAnimationsCode.bind" />
<Content Include="SamplePages\DispatcherHelper\DispatcherHelperCode.bind" />
<Content Include="SamplePages\DispatcherQueueHelper\DispatcherQueueHelperCode.bind" />
<Content Include="SamplePages\TextToolbar\TextToolbar.bind" />
<Content Include="SamplePages\DockPanel\DockPanel.bind">
<SubType>Designer</SubType>
Expand Down Expand Up @@ -726,8 +726,8 @@
<Compile Include="SamplePages\BackgroundTaskHelper\BackgroundTaskHelperPage.xaml.cs">
<DependentUpon>BackgroundTaskHelperPage.xaml</DependentUpon>
</Compile>
<Compile Include="SamplePages\DispatcherHelper\DispatcherHelperPage.xaml.cs">
<DependentUpon>DispatcherHelperPage.xaml</DependentUpon>
<Compile Include="SamplePages\DispatcherQueueHelper\DispatcherQueueHelperPage.xaml.cs">
<DependentUpon>DispatcherQueueHelperPage.xaml</DependentUpon>
</Compile>
<Compile Include="SamplePages\DropShadowPanel\DropShadowPanelPage.xaml.cs">
<DependentUpon>DropShadowPanelPage.xaml</DependentUpon>
Expand Down Expand Up @@ -1151,7 +1151,7 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="SamplePages\DispatcherHelper\DispatcherHelperPage.xaml">
<Page Include="SamplePages\DispatcherQueueHelper\DispatcherQueueHelperPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
// From a UI thread, capture the DispatcherQueue once:
var dispatcherQueue = DispatcherQueue.GetForCurrentThread();

// The use it from any other thread
int crossThreadReturnedValue = await Task.Run<int>( async () =>
{
// Task.Run() will guarantee the given piece of code be executed on a seperate thread pool.
// This is used to simulate the scenario of updating the UI element from a different thread.
int returnedFromUIThread = await DispatcherHelper.ExecuteOnUIThreadAsync<int>(() =>
int returnedFromUIThread = await dispatcherQueue.ExecuteOnUIThreadAsync<int>(() =>
{
NormalTextBlock.Text = "Updated from a random thread!";
return 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Page x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.DispatcherHelperPage"
<Page x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.DispatcherQueueHelperPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Expand Down
Loading