i'm making a USB-related program.
i'm testing MS official example, but DeviceWatcher.Removed event coulndn't be called when i disconnected USB Device, just be called DeviceWatcher.Updated.
i'm testing DeviceWatcher by My Mobile Phone and USB UART Device.
code is here. i found that code somewhere in MSDN. (and i modified a little.)
namespace USBTest
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
///
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
Windows.UI.Core.CoreDispatcher dispatcher;
public static DeviceWatcher watcher = null;
public static int count = 0;
public static DeviceInformation[] interfaces = new DeviceInformation[65535];
public static bool isEnumerationComplete = false;
public static string StopStatus = null;
async void WatchDevices(object sender, RoutedEventArgs eventArgs)
{
try
{
dispatcher = Window.Current.CoreWindow.Dispatcher;
watcher = DeviceInformation.CreateWatcher();
// Add event handlers
watcher.Added += watcher_Added;
watcher.Removed += watcher_Removed;
watcher.Updated += watcher_Updated;
watcher.EnumerationCompleted += watcher_EnumerationCompleted;
watcher.Stopped += watcher_Stopped;
watcher.Start();
OutputText.Text = "Enumeration started.";
}
catch (ArgumentException)
{
//The ArgumentException gets thrown by FindAllAsync when the GUID isn't formatted properly
//The only reason we're catching it here is because the user is allowed to enter GUIDs without validation
//In normal usage of the API, this exception handling probably wouldn't be necessary when using known-good GUIDs
OutputText.Text = "Caught ArgumentException. Failed to create watcher.";
}
}
async void StopWatcher(object sender, RoutedEventArgs eventArgs)
{
try
{
if (watcher.Status == Windows.Devices.Enumeration.DeviceWatcherStatus.Stopped)
{
StopStatus = "The enumeration is already stopped.";
}
else
{
watcher.Stop();
}
}
catch (ArgumentException)
{
OutputText.Text = "Caught ArgumentException. Failed to stop watcher.";
}
}
async void watcher_Added(DeviceWatcher sender, DeviceInformation deviceInterface)
{
interfaces[count] = deviceInterface;
count += 1;
if (isEnumerationComplete)
{
await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
DisplayDeviceInterfaceArray();
});
}
}
async void watcher_Updated(DeviceWatcher sender, DeviceInformationUpdate devUpdate)
{
int count2 = 0;
foreach (DeviceInformation deviceInterface in interfaces)
{
if (count2 < count)
{
if (interfaces[count2].Id == devUpdate.Id)
{
//Update the element.
interfaces[count2].Update(devUpdate);
}
}
count2 += 1;
}
await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
OutputText.Text = "Enumeration updated. ";
DisplayDeviceInterfaceArray();
});
}
async void watcher_Removed(DeviceWatcher sender, DeviceInformationUpdate devUpdate)
{
int count2 = 0;
//Convert interfaces array to a list (IList).
List<DeviceInformation> interfaceList = new List<DeviceInformation>(interfaces);
foreach (DeviceInformation deviceInterface in interfaces)
{
if (count2 < count)
{
if (interfaces[count2].Id == devUpdate.Id)
{
//Remove the element.
interfaceList.RemoveAt(count2);
}
}
count2 += 1;
}
//Convert the list back to the interfaces array.
interfaces = interfaceList.ToArray();
count -= 1;
await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
OutputText.Text = "Enumeration device was removed. ";
DisplayDeviceInterfaceArray();
});
}
async void watcher_EnumerationCompleted(DeviceWatcher sender, object args)
{
isEnumerationComplete = true;
await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
OutputText.Text = "Enumeration complete. ";
DisplayDeviceInterfaceArray();
});
}
async void watcher_Stopped(DeviceWatcher sender, object args)
{
if (watcher.Status == Windows.Devices.Enumeration.DeviceWatcherStatus.Aborted)
{
StopStatus = "Enumeration stopped unexpectedly. Click Watch to restart enumeration.";
}
else if (watcher.Status == Windows.Devices.Enumeration.DeviceWatcherStatus.Stopped)
{
StopStatus = "You requested to stop the enumeration. Click Watch to restart enumeration.";
}
}
async void DisplayDeviceInterfaceArray()
{
DeviceInterfacesOutputList.Items.Clear();
int count2 = 0;
foreach (DeviceInformation deviceInterface in interfaces)
{
if (count2 < count)
{
DisplayDeviceInterface(deviceInterface);
}
count2 += 1;
}
}
async void DisplayDeviceInterface(DeviceInformation deviceInterface)
{
var id = "Id:" + deviceInterface.Id;
var name = deviceInterface.Name;
var isEnabled = "IsEnabled:" + deviceInterface.IsEnabled;
var item = id + " is \n" + name + " and \n" + isEnabled;
DeviceInterfacesOutputList.Items.Add(item);
}
}
}
<Page
x:Class="USBTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:USBTest"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid x:Name="ContentRoot" Margin="100,20,100,20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Header -->
<StackPanel x:Name="Header" Grid.Row="0">
<StackPanel Orientation="Horizontal"/>
</StackPanel>
<!-- Content -->
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Grid.Row="1" ZoomMode="Disabled">
<StackPanel x:Name="ContentPanel">
<TextBlock Text="Device Enumeration Sample" Margin="0,25,0,20" Height="25" />
<StackPanel x:Name="InputPanel" Orientation="Horizontal" HorizontalAlignment="Left" Height="266">
<StackPanel/>
<StackPanel x:Name="Description" MaxWidth="900">
<!-- Enumerate Device Interfaces -->
<StackPanel x:Name="EnumerateDevicesInput" Height="270" Width="857">
<TextBlock Text="Input" Margin="0,25,0,20" />
<TextBlock TextWrapping="Wrap" Text="This example app incrementally enumerates devices, adding them to a list each time a device is found, and also watching for updates. After enumeration is complete, the app prints the list of devices. The app reprints the list if devices are updated, removed, or added." HorizontalAlignment="Left"/>
<StackPanel Orientation="Horizontal" Margin="0,10,0,0"/>
<StackPanel Orientation="Horizontal" Margin="0,10,0,0"/>
<Button Name="WatchAllDevices" Content="Watch (All devices)" Margin="0,10,10,0" Click="WatchDevices" />
<Button Name="StopAllWatcher" Content="Stop" Margin="0,10,10,0" Click="StopWatcher" />
</StackPanel>
</StackPanel>
</StackPanel>
<TextBlock Text="Output" Margin="0,25,0,20" />
<!-- Output section -->
<StackPanel x:Name="Output" HorizontalAlignment="Left">
<TextBlock Name="OutputText" />
<!-- Device Interfaces-->
<ListBox Name="DeviceInterfacesOutputList" IsEnabled="False" BorderThickness="0" />
</StackPanel>
</StackPanel>
</ScrollViewer>
</Grid>
</Page>
Related
My CaptureElements are showing strange behavior. When I set a instantiated MediaCapture as the CaptureElements Source and then call MediaCapture.StartPreviewAsync() the CaptureElement doesn't show anything.
I have one Application (main-app) with a functional BarcodeScanner on the LoginPage.
-> Works!
Then I wanted to copy the same code to the SettingsPage with small modifications so in case of several attached cameras, the default one can be set.
-> Doesn't work
Then I tried to run the main-app with the help of the remote debugger on other windows tablets with same Windows 10 Version as my machine (keep in mind, that the BarcodeScanner on the Login-Screen works on my machine).
-> doesn't work
Because of these failures I copied the running code from the main-apps LoginPage to a completely new solution (lets call it test-app) with the same settings as the original one. I even experimented with referencing the same Dlls, implementing the same design pattern etc.
-> doesn't work
My Machine:
Win 10 Pro
Version 1809
Build 17763.652
DevEnv:
MS Visual Studio 2019 Pro
Vers. 16.1.6
EDIT: As minimum required Windows Version I selected Build 16229 and
my target Version is Build 17763 (my systems Win version)
The "Allow apps to access your camera"-Option in the Widows Settings is switched to ON, so all apps are allowed to access the camera.
Xaml
<Page
x:Class="QrCodeTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:QrCodeTest"
xmlns:vm="using:QrCodeTest.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.DataContext>
<vm:TestViewModel x:Name="ViewModel" />
</Page.DataContext>
<ScrollViewer>
<StackPanel>
<Button Content="Start Preview" HorizontalAlignment="Center" Click="Button_Click" Margin="5" />
<CaptureElement x:Name="capturePreview" HorizontalAlignment="Center" Stretch="Uniform" Width="0" Height="0" Margin="10" />
<Button Content="Stop Preview" HorizontalAlignment="Center" Click="Button_Click_1" Margin="5" />
<TextBlock Text="{Binding Etikett, Mode=TwoWay}" HorizontalAlignment="Center" Margin="5" />
</StackPanel>
</ScrollViewer>
</Page>
CodeBehind
private BarcodeScanner scanner { get; set; }
private ClaimedBarcodeScanner claimedScanner { get; set; }
private MediaCapture captureManager { get; set; }
internal async Task StartScannerAsync () {
capturePreview.Visibility = Visibility.Visible;
capturePreview.Width = 400; capturePreview.Height = 300;
scanner = null;
scanner = await DeviceHelpers.GetFirstDeviceAsync(BarcodeScanner.GetDeviceSelector(connectionTypes), async (id) => await BarcodeScanner.FromIdAsync(id));
if (scanner != null) {
captureManager = new MediaCapture();
claimedScanner = await scanner.ClaimScannerAsync();
if (claimedScanner != null) {
claimedScanner.ReleaseDeviceRequested += claimedScanner_ReleaseDeviceRequested;
claimedScanner.DataReceived += claimedScanner_DataReceived;
claimedScanner.IsDecodeDataEnabled = true;
IReadOnlyList<uint> supportedSymbologies = await scanner.GetSupportedSymbologiesAsync();
foreach (uint symbology in supportedSymbologies) {
listOfSymbologies.Add(new SymbologyListEntry(symbology));
}
await claimedScanner.EnableAsync();
MediaCaptureInitializationSettings _captureInitSettings = new MediaCaptureInitializationSettings {
VideoDeviceId = scanner.VideoDeviceId,
StreamingCaptureMode = StreamingCaptureMode.AudioAndVideo,
PhotoCaptureSource = PhotoCaptureSource.VideoPreview
};
await captureManager.InitializeAsync(_captureInitSettings);
capturePreview.Source = captureManager;
try {
// Change to false, in case you wanna compare different methods of doing the same
bool Like_MP_PAT_UWP = false;
if (Like_MP_PAT_UWP) {
await capturePreview.Source.StartPreviewAsync();
await claimedScanner.StartSoftwareTriggerAsync();
} else {
LocalDataContext.Etikett = "await captureManager.StartPreviewAsync();";
await captureManager.StartPreviewAsync();
await claimedScanner.StartSoftwareTriggerAsync();
Thread.Sleep(2000);
await claimedScanner.StopSoftwareTriggerAsync();
await captureManager.StopPreviewAsync();
LocalDataContext.Etikett = "await capturePreview.Source.StartPreviewAsync();";
await capturePreview.Source.StartPreviewAsync();
await claimedScanner.StartSoftwareTriggerAsync();
Thread.Sleep(2000);
await claimedScanner.StopSoftwareTriggerAsync();
await capturePreview.Source.StopPreviewAsync();
LocalDataContext.Etikett = "await claimedScanner.ShowVideoPreviewAsync();";
await claimedScanner.ShowVideoPreviewAsync();
await claimedScanner.StartSoftwareTriggerAsync();
Thread.Sleep(2000);
await claimedScanner.StopSoftwareTriggerAsync();
claimedScanner.HideVideoPreview();
}
} catch (Exception e) {
Exception x = e; displayRequest.RequestRelease();
} finally {
LocalDataContext.Etikett = string.Empty;
}
}
}
}
ViewModel:
public class TestViewModel: INotifyPropertyChanged {
public static TestViewModel Instance { get; set; }
private string _Etikett;
public string Etikett { get { return _Etikett; } set { _Etikett = value; NotifyPropertyChanged(); } }
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged ([CallerMemberName] String propertyName = "") {
//PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
if (PropertyChanged != null) {
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I've wasted already 4 working days just to compare the solutions, the codes etc. The above code was copied from the test-app but it's mostly identical to the one on the main-apps LoginPage (except for the "if (Like_MP_PAT_UWP) {...}".
Every hint is welcome.
Thank you in advance.
The Problem was Kaspersky Endpoint Security's "advanced Threat Protection/host intrusion prevention"-setting. It prevented ALL apps outside from our dev-harddrive (i. e. on our tablets or from our network-drive) to access the camera (Dev-Drive = "Trusted Zone").
It was necessary to reconfigure that feature in Kaspersky Endpoint Security for the whole environment (declare necessary locations/clients as a trusted zone).
Hope, this might help someone with a similar problem or at least give a hint to someone.
Just spit-balling here, but I'd suggest attempting to reduce your test to just code that controls the MediaCapture object as much as possible, as that seems to be the symptom where you describe the main issue.
After that, try lowering the SharingMode of the camera to just read-only, in case another app is using the camera with exclusive access. Also, you can reduce the pop up consent check to just the camera, and not have the microphone consent. Sometimes if you accidentally don't agree during the consent pop-up, the app will be denied access to the camera until you allow it again from the system settings (Settings -> Privacy -> Camera).
Below is a sub-optimal and boiled down version of what you described above, but all parts included. I tried to segregate your starting a barcode session from disposing things. Using the MS samples as a guide will be far more reliable than this one. Nonetheless, there's lots more trace points to add, but below has a few traces around where the MediaCapture fails, and other points in the barcode scanner enable section. Hope it helps.
using System;
using System.Collections.Generic;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Devices.PointOfService;
using System.Threading.Tasks;
using Windows.Media.Capture;
using Windows.Devices.Enumeration;
using System.Diagnostics;
using Windows.Storage.Streams;
namespace StackOverflowQrTest
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
if (claimedScanner == null)
{
await StartScannerAsync();
}
}
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
await StopScannerAsync();
}
private BarcodeScanner scanner { get; set; }
private ClaimedBarcodeScanner claimedScanner { get; set; }
private MediaCapture captureManager { get; set; }
internal async Task StartScannerAsync()
{
capturePreview.Visibility = Visibility.Visible;
capturePreview.Width = 400; capturePreview.Height = 300;
scanner = await DeviceHelpers.GetFirstDeviceAsync(BarcodeScanner.GetDeviceSelector(), async (id) => await BarcodeScanner.FromIdAsync(id));
if (scanner != null)
{
claimedScanner = await scanner.ClaimScannerAsync();
if (claimedScanner != null)
{
claimedScanner.ReleaseDeviceRequested += ClaimedScanner_ReleaseDeviceRequested;
claimedScanner.DataReceived += ClaimedScanner_DataReceived;
claimedScanner.IsDecodeDataEnabled = true;
await claimedScanner.EnableAsync();
try
{
bool haveAssociatedCamera = !string.IsNullOrEmpty(scanner.VideoDeviceId);
if (haveAssociatedCamera)
{
captureManager = new MediaCapture();
captureManager.Failed += CaptureManager_Failed;
MediaCaptureInitializationSettings _captureInitSettings = new MediaCaptureInitializationSettings
{
VideoDeviceId = scanner.VideoDeviceId,
SharingMode = MediaCaptureSharingMode.SharedReadOnly, // share
StreamingCaptureMode = StreamingCaptureMode.Video // just video
};
await captureManager.InitializeAsync(_captureInitSettings);
capturePreview.Source = captureManager;
}
UpdateMessage("waiting..." + (!haveAssociatedCamera ? "But scanner not camera type" : ""));
if (captureManager != null) await captureManager.StartPreviewAsync();
await claimedScanner.StartSoftwareTriggerAsync();
}
catch (Exception e)
{
UpdateMessage(e.Message);
Debug.WriteLine("EXCEPTION: " + e.Message);
}
}
else
{
UpdateMessage("Could not claim barcode scanner");
}
}
else
{
UpdateMessage("No barcode scanners found");
}
}
private void CaptureManager_Failed(MediaCapture sender, MediaCaptureFailedEventArgs errorEventArgs)
{
string msg = string.Format("MediaCapture_Failed: (0x{0:X}) {1}", errorEventArgs.Code, errorEventArgs.Message);
UpdateMessage(msg);
}
internal async Task StopScannerAsync()
{
if (captureManager != null)
{
if (captureManager.CameraStreamState == Windows.Media.Devices.CameraStreamState.Streaming)
{
await captureManager.StopPreviewAsync();
}
captureManager.Dispose();
captureManager = null;
}
if (claimedScanner != null)
{
claimedScanner.Dispose();
claimedScanner = null;
}
if (scanner != null)
{
scanner.Dispose();
scanner = null;
}
}
private void ClaimedScanner_DataReceived(ClaimedBarcodeScanner sender, BarcodeScannerDataReceivedEventArgs args)
{
var scanDataLabelReader = DataReader.FromBuffer(args.Report.ScanDataLabel);
string barcode = scanDataLabelReader.ReadString(args.Report.ScanDataLabel.Length);
UpdateMessage(barcode);
}
private void ClaimedScanner_ReleaseDeviceRequested(object sender, ClaimedBarcodeScanner e)
{
UpdateMessage("Another process is requesting barcode scanner device.");
e.RetainDevice();
}
private async void UpdateMessage (string message)
{
await LastBarcodeRead.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
LastBarcodeRead.Text = message;
});
}
}
public partial class DeviceHelpers
{
// We use a DeviceWatcher instead of DeviceInformation.FindAllAsync because
// the DeviceWatcher will let us see the devices as they are discovered,
// whereas FindAllAsync returns results only after discovery is complete.
public static async Task<T> GetFirstDeviceAsync<T>(string selector, Func<string, Task<T>> convertAsync)
where T : class
{
var completionSource = new TaskCompletionSource<T>();
var pendingTasks = new List<Task>();
DeviceWatcher watcher = DeviceInformation.CreateWatcher(selector);
watcher.Added += (DeviceWatcher sender, DeviceInformation device) =>
{
Func<string, Task> lambda = async (id) =>
{
T t = await convertAsync(id);
if (t != null)
{
completionSource.TrySetResult(t);
}
};
pendingTasks.Add(lambda(device.Id));
};
watcher.EnumerationCompleted += async (DeviceWatcher sender, object args) =>
{
// Wait for completion of all the tasks we created in our "Added" event handler.
await Task.WhenAll(pendingTasks);
// This sets the result to "null" if no task was able to produce a device.
completionSource.TrySetResult(null);
};
watcher.Start();
// Wait for enumeration to complete or for a device to be found.
T result = await completionSource.Task;
watcher.Stop();
return result;
}
}
}
Where main xaml is...
<Page
x:Class="StackOverflowQrTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:StackOverflowQrTest"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer>
<StackPanel>
<Button Content="Start Preview" HorizontalAlignment="Center" Click="Button_Click" Margin="5" />
<CaptureElement x:Name="capturePreview" HorizontalAlignment="Center" Stretch="Uniform" Width="0" Height="0" Margin="10" />
<Button Content="Stop Preview" HorizontalAlignment="Center" Click="Button_Click_1" Margin="5" />
<TextBox Header="LastBarcode" Name="LastBarcodeRead" IsReadOnly="True" HorizontalAlignment="Center" Margin="5" />
</StackPanel>
</ScrollViewer>
</Page>
I'm using Visual Studio 2015, WPF, C#.
This is example code to a larger project that replicates the Error.
Test Project source here:
https://www.dropbox.com/s/xtlpfhecm1mfv5m/Downloader.zip?dl=0
I have a ComboBox where you choose a File Download.
In the example it downloads the StackOverflow logo png from imgur to Downloads folder.
Problem
ComboBox SelectedItem Error
if ((string)cboDownload.SelectedItem == "File 1") { ... }
The calling thread cannot access this object because a different thread owns it.
I add a Dispatcher inside the Thread.
But the Dispatcher causes the program to freeze when you press the Download button.
Solutions
I can only get it to work if I set the ComboBox Selected Item to a string before the Thread:
string cboDownloadItem = cboDownload.SelectedItem.ToString();
if ((string)cboDownloadItem == "File 1") { ... }
But I'd rather not have to do that.
XAML
<Label x:Name="labelProgressInfo"
Content="" HorizontalAlignment="Center"
Margin="10,55,10,0"
VerticalAlignment="Top"
Width="497"/>
<ProgressBar x:Name="progressBar"
HorizontalAlignment="Left"
Height="24" Margin="10,89,0,0"
VerticalAlignment="Top"
Width="487"/>
<ComboBox x:Name="cboDownload"
HorizontalAlignment="Left"
Margin="122,171,0,0"
VerticalAlignment="Top"
Width="120"
SelectedIndex="0">
<System:String>File 1</System:String>
<System:String>File 2</System:String>
</ComboBox>
<Button x:Name="btnDownload"
Content="Download"
HorizontalAlignment="Left"
Margin="278,173,0,0"
VerticalAlignment="Top"
Width="75"
Click="btnDownload_Click"/>
Strings
string fileBaseUrl = "https://i.imgur.com/";
string fileName = string.Empty;
string localPath = Environment.ExpandEnvironmentVariables(#"%USERPROFILE%") + "\\Downloads\\";
Download Button
private void btnDownload_Click(object sender, RoutedEventArgs e)
{
// Start New Thread
//
Thread thread = new Thread(() =>
{
Dispatcher.BeginInvoke((MethodInvoker)delegate
{
// ComboBox Selected Download
//
if ((string)cboDownload.SelectedItem == "File 1")
{
// StackOverflow Logo
fileName = "WTminjY.png";
}
waiter = new ManualResetEvent(false);
Uri downloadUrl = new Uri(fileBaseUrl + fileName);
wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
wc.DownloadFileAsync(downloadUrl, localPath + fileName);
// Progress TextBox
progressInfo = "Downloading...";
// Wait for Download to complete
waiter.WaitOne();
// Progress TextBox
progressInfo = "Download Complete";
});
});
// Start Download Thread
//
thread.Start();
}
Download Handlers
public void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
// Progress TextBox
Dispatcher.BeginInvoke((MethodInvoker)delegate
{
labelProgressInfo.Content = progressInfo;
});
// Progress Bar
Dispatcher.BeginInvoke((MethodInvoker)delegate
{
double bytesIn = double.Parse(e.BytesReceived.ToString());
double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
double percentage = bytesIn / totalBytes * 100;
progressBar.Value = int.Parse(Math.Truncate(percentage).ToString());
});
}
public void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
waiter.Set();
// Progress TextBox
Dispatcher.BeginInvoke((MethodInvoker)delegate
{
labelProgressInfo.Content = progressInfo;
});
}
whenever i enter usename and password it throws an exception. but when i run it individually it runs perfectly.
Exception thrown: 'System.Windows.Markup.XamlParseException' in PresentationFramework.dll
Code
private void testing()
{
try
{
Thread newWindowThread = new Thread(new ThreadStart(() =>
{
SynchronizationContext.SetSynchronizationContext(
new DispatcherSynchronizationContext(
Dispatcher.CurrentDispatcher));
var loading_Win = new Loading_Window();
loading_Win.Show();
loading_Win.Closed += (s, ex) =>
Dispatcher.CurrentDispatcher.BeginInvokeShutdown(
DispatcherPriority.Background);
// Start the Dispatcher Processing
System.Windows.Threading.Dispatcher.Run();
}));
// Set the apartment state
newWindowThread.SetApartmentState(ApartmentState.STA);
// Make the thread a background thread
newWindowThread.IsBackground = true;
// Start the thread
newWindowThread.Start();
}
catch (Exception ex)
{ }
}
this is the loading window cs
public partial class Loading_Window : MetroWindow
{
public Random rnd = new Random();
public static int intIteration = 1;
private System.Windows.Forms.Timer timer1;
public Loading_Window()
{
InitializeComponent();
InitTimer();
this.Closing += Loading_Window_Closing;
}
private void Loading_Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
//Process[] pro = null;
//try
//{
// pro = Process.GetProcessesByName("LeanPims");
// pro[0].Kill();
//}
//catch (Exception ex)
//{ }
//Process.GetCurrentProcess().Kill();
}
public void InitTimer()
{
intIteration = 0;
timer1 = new System.Windows.Forms.Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = 300; // in miliseconds
timer1.Start();
}
public void timer1_Tick(object sender, EventArgs e)
{
intIteration += rnd.Next(1, 8);
label1.Content = intIteration.ToString() + " %";
try
{
if (intIteration >= 100)
{
timer1.Stop();
timer1 = null;
this.Close();
}
}
catch (Exception ex) { }
}
}
this is the loading window xaml
<Viewbox Stretch="Fill">
<Grid Height="500" Width="700" >
<Image Stretch="Fill" Width="300" Height="350" gif:ImageBehavior.AnimatedSource="Images\Loading1.gif" />
<Rectangle HorizontalAlignment="Left" Height="45" Margin="298,228,0,0" StrokeThickness="2" VerticalAlignment="Top" Width="103" Fill="White"/>
<Label Content="" x:Name="label1" HorizontalAlignment="Left" Height="36" Margin="327,236,0,0" VerticalAlignment="Top" Width="62" FontSize="18" FontFamily="Arial" Foreground="#FF837F7F" Background="{x:Null}" FontWeight="Bold"/>
<Canvas x:Name="c1" HorizontalAlignment="Left" Height="406" Margin="112,38,0,0" VerticalAlignment="Top" Width="481"/>
</Grid>
</Viewbox>
Exception thrown: 'System.Windows.Markup.XamlParseException' in PresentationFramework.dll
Initialization of 'System.Windows.Controls.Button' threw an exception.
The problem is that you use a System.Windows.Forms.Timer to set label1.Content.
You either have to use a System.Windows.Threading.DispatcherTimer instead or you have to invoke the Dispatcher manually using:
Dispatcher.Invoke(() => label1.Content = intIteration.ToString() + " %");
The same is true for all other UI-related calls.
If you don't want to use a DispatcherTimer then you have to do this as well:
Dispatcher.Invoke(() => this.Close());
But there have to be even more UI-related statements because your XamlParseException states that Initialization of 'System.Windows.Controls.Button' threw an exception and I don't see a single Button in the code you posted.
So check if there are any other UI-related calls and invoke them using the right Dispatcher. (Especially pay attention that you don't use Application.Current.Dispatcher in your Loading_Window if you have multiple Dispatchers in your application. Just use Dispatcher or Dispatcher.CurrentDispatcher in that case.)
And last but not least I'm pretty sure that there is yet another InnerException in the XamlParseException that says Initialization of 'System.Windows.Controls.Button' threw an exception. Please check that as well. It could be another cause or it just could be the same as above. Either it is in the constructor of a control that inherits from Button or it is probably somewhere in the XAML.
I have list of images which I need to download. I am using BackgroundDownloader and DownloadOperation. I have placed progressbar to show the number of files downloaded.
The UI always update 1 less than downloaded file. Can anyone please point where I am missing.
Here is the code:
C#
public sealed partial class MainPage : Page
{
int count = 0;
public StorageFile ErrorFile { get; set; }
private List<DownloadOperation> activeDownloads = new List<DownloadOperation>();
List<string> guid = new List<string>();
public MainPage()
{
this.InitializeComponent();
}
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
await StartDownload();
}
private async Task StartDownload()
{
BackgroundDownloader downloader = new BackgroundDownloader();
downloader.CostPolicy = BackgroundTransferCostPolicy.UnrestrictedOnly;
List<Task> downloadCompletionTasks = new List<Task>();
List<string> files = GetFiles();
totalCount.Text = (files.Count).ToString();
progressBar1.Maximum = (files.Count);
foreach (string url in files)
{
StorageFile file = null;
file = await ApplicationData.Current.LocalFolder.CreateFileAsync(DateTime.Now.Ticks.ToString() + ".jpg", CreationCollisionOption.ReplaceExisting);
DownloadOperation op = downloader.CreateDownload(new Uri(url), file);
activeDownloads.Add(op);
}
//This forloop cannot be clubbed with above for loop because progressChanged event is accessing activeDownloads.
//In case of clubbing with above loop collection modified loop will be thrown.
foreach (DownloadOperation op in activeDownloads)
{
Progress<DownloadOperation> progress = new Progress<DownloadOperation>(progressChanged);
CancellationTokenSource cancellationToken = new CancellationTokenSource();
downloadCompletionTasks.Add(op.StartAsync().AsTask(cancellationToken.Token, progress));
}
Task status = Task.WhenAll(downloadCompletionTasks);
}
private async void progressChanged(DownloadOperation downloadOperation)
{
foreach (DownloadOperation op in activeDownloads)
{
if (!guid.Contains(op.Guid.ToString()))
{
if (op.Progress.Status == BackgroundTransferStatus.Completed)
{
await UpdateUI(downloadOperation, op);
}
else if (op.Progress.Status == BackgroundTransferStatus.Error)
{
await UpdateUI(downloadOperation, op);
}
}
}
}
private async Task UpdateUI(DownloadOperation downloadOperation, DownloadOperation op)
{
guid.Add(op.Guid.ToString());
await this.Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
{
count = count + 1; //guid count can be used as well
progressBar1.Value = count;
progressCount.Text = count.ToString();
});
}
private List<String> GetFiles()
{
List<string> imgurl = new List<string>();
imgurl.Add("http://images5.fanpop.com/image/photos/26700000/Snoopy-peanuts-26798453-1024-768.jpg");
imgurl.Add("http://images.fanpop.com/images/image_uploads/Peanut-Wallpapers-peanuts-99522_1024_768.jpg");
imgurl.Add("http://images5.fanpop.com/image/photos/25300000/peanuts-peanuts-25369428-800-600.jpg");
imgurl.Add("http://images6.fanpop.com/image/photos/37200000/Peanuts-Movie-Wallpaper-peanuts-37225534-3996-2160.jpg");
imgurl.Add("http://images.fanpop.com/images/image_uploads/Peanut-Wallpapers-peanuts-99520_1024_768.jpg");
imgurl.Add("http://4.bp.blogspot.com/-wU0ljNbhyUc/TYo-LLNzqiI/AAAAAAAACQU/YxAHEOAFfCk/s1600/snoopy+peanuts+desktop+wallpaper.jpg");
imgurl.Add("http://images5.fanpop.com/image/photos/26700000/Peanuts-peanuts-26798652-1024-768.jpg");
imgurl.Add("http://brandthunder.com/wp/wp-content/uploads/2014/07/Peanuts-Wallpaper.jpg");
imgurl.Add("http://3.bp.blogspot.com/-OT_HLjvXiSM/UXbByYXDU3I/AAAAAAAAAdo/6kQv7OO0v4I/s1600/snoopy-woodstock_00392750.jpg");
imgurl.Add("http://images6.fanpop.com/image/photos/33100000/Snoopy-wallpaper-snoopy-33124725-1024-768.jpg");
return imgurl;
}
}
Xaml
<Grid Background="DarkBlue">
<!--<Grid Background="Black" Opacity="0.6" Grid.Row="0"/>-->
<Grid Grid.Row="0" VerticalAlignment="Center">
<Grid VerticalAlignment="Center" Grid.Row="0" Margin="50" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="20"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="Downloading" x:Name="fileName" FontSize="20" Grid.Row="0"/>
<ProgressBar x:Name="progressBar1" IsIndeterminate="False" Grid.Row="1"/>
<!--<TextBlock x:Name="percentTextBlock" Text="{Binding TotalProgressPercent}" Grid.Row="2" HorizontalAlignment="Center"/>-->
<TextBlock FontSize="20" x:Name="progressCount" Text="0" Grid.Row="2" HorizontalAlignment="left"/>
<TextBlock FontSize="20" x:Name="totalCount" Text="50" Grid.Row="2" HorizontalAlignment="Right"/>
</Grid>
</Grid>
</Grid>
This is most likely a threading issue. Turn your guid collection into a HashSet. It's possible that the check to see if the guid is part of the list fails if the event is fired at the same time and the guid would be added multiple times. A HashSet will prevent the guid from being added twice.
Your count variable is not safe as it could be overwritten by calls to the method at the same time. You should use the new HashSet's count.
--Edit--
Since you already have a list of active downloads, just remove the one that completes like this:
private async void progressChanged(DownloadOperation downloadOperation)
{
var status = downloadOperation.Progress.Status;
if (status == BackgroundTransferStatus.Completed || status == BackgroundTransferStatus.Error)
{
await UpdateUI(downloadOperation);
}
}
private async Task UpdateUI(DownloadOperation downloadOperation)
{
await this.Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
{
activeDownloads.Remove(downloadOperation);
var activeCount = activeDownloads.Count;
progressBar1.Value = activeCount;
progressCount.Text = activeCount.ToString();
});
}
This code is written to get best (maximum) resolution for cam and then take the photo for that but it is taking photo only for VGA while cam has 8 mega pixel resolution. Please correct me what is the wrong with this code. thanks
<Page
x:Class="win8appbycrs.BlankPage2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:win8appbycrs"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Image x:Name="image" HorizontalAlignment="Left" Height="424" Margin="254,45,0,0" VerticalAlignment="Top" Width="619"/>
<Button Content="Set" HorizontalAlignment="Left" Margin="978,293,0,0" VerticalAlignment="Top" Click="Button_Click"/>
<CaptureElement x:Name="ce" HorizontalAlignment="Left" Height="268" Margin="97,490,0,0" VerticalAlignment="Top" Width="421" Stretch="Fill"/>
<ComboBox x:Name="ComboBox1" HorizontalAlignment="Left" Margin="659,474,0,0" VerticalAlignment="Top" Width="120"/>
<Button Content="Capture" HorizontalAlignment="Left" Margin="840,499,0,0" VerticalAlignment="Top" Click="Button_Click_1"/>
<Image x:Name="Img" HorizontalAlignment="Left" Height="225" Margin="254,133,0,0" VerticalAlignment="Top" Width="356"/>
</Grid>
C# Code:
public BlankPage2()
{
InitializeComponent();
mediaCaptureMgr = new MediaCapture();
StartPreview();
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
int max_res = 0;
int selected = 0;
string sCameraName;
var interfaces = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(Windows.Devices.Enumeration.DeviceClass.VideoCapture);
foreach (DeviceInformation deviceInterface in interfaces)
{
sCameraName = deviceInterface.Name.ToString();
MediaCaptureInitializationSettings captureInitSettings = new Windows.Media.Capture.MediaCaptureInitializationSettings();
captureInitSettings.VideoDeviceId = deviceInterface.Id;
captureInitSettings.PhotoCaptureSource = PhotoCaptureSource.VideoPreview;
//enumerate each camera for supported configurations
MediaCapture mediaCaptureMgr = new Windows.Media.Capture.MediaCapture();
await mediaCaptureMgr.InitializeAsync(captureInitSettings);
//System.Collections.Generic.IReadOnlyList<IMediaEncodingProperties> res = mediaCaptureMgr.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoRecord);
res = mediaCaptureMgr.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoPreview);
//if no settings available, bail
if (res.Count < 1) return;
//list the number of setting combinations for the device
string sCount = sCameraName + ": " + res.Count.ToString();
// ComboBox1.Items.Add(sCount);
//list the different format settings
for (int i = 0; i < res.Count; i++)
{
VideoEncodingProperties vp = (VideoEncodingProperties)res[i];
if (vp.Width * vp.Height > max_res)
{
resolutionMax=vp;
max_res = (int)vp.Width;
selected = i;
}
}
}
setres(selected);
}
async void StartPreview()
{
try
{
await mediaCaptureMgr.InitializeAsync();
ce.Source = mediaCaptureMgr;
await mediaCaptureMgr.StartPreviewAsync();
}
catch (Exception ex)
{
mediaCaptureMgr = null;
GC.Collect();
}
}
private async void setres(int maxres)
{
await mediaCaptureMgr.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoPreview , res[maxres]);
}
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
var captureSettings = new ImageEncodingProperties();
captureSettings.Height = resolutionMax.Height;
captureSettings.Width = resolutionMax.Width;
captureSettings.Subtype = "Jpeg";
// Requires documentsLibrary capability
var folder = ApplicationData.Current.RoamingFolder;
var folder1 = KnownFolders.PicturesLibrary;
var file = await folder.CreateFileAsync(#"Captured.jpg", Windows.Storage.CreationCollisionOption.GenerateUniqueName);
await mediaCaptureMgr.CapturePhotoToStorageFileAsync(captureSettings, file);
Img.Source = new BitmapImage(new Uri(#file.Path));
await file.CopyAsync(folder1);
}
Just taking a guess here - instead of using VideoPreview to get your resolutions, you should try using Photo:
//res = mediaCaptureMgr.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoPreview);
res = mediaCaptureMgr.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.Photo);