带有MVVMLight的通用应用程序。
所以我开始想,为什么所有的SDK示例都是从代码后台完成的,而不是使用可靠的包装器类。
所以我想写一个可重用的包装类。不走运。即使尝试将该包装器添加到ViewModel中,仍然没有成功。
在MainView.xaml.cs中运行良好
IBandInfo[] pairedBands = BandClientManager.Instance.GetBandsAsync().Result;
if (pairedBands.Length > 0)
{
using (IBandClient bandClient = await BandClientManager.Instance.ConnectAsync(pairedBands[0]))
{
}
}当我转向任何类型的OOP或视图模型时,ConnectAsync永远不会返回或抛出异常。我试了20种不同的方法,SDK坏了吗?这是怎么回事?没有消息,没有抛出,只是永远不会返回。
如果我抛出Code fine,它就会工作得很好,并在1/2秒内返回客户端。
到目前为止,我已经在这上面花了5-6个小时。我想为SDK创建一个可靠的包装类,这样我就可以从模型中调用简单的调用,并做像StartListener(MicrosoftBandSensor sensorToActivate)这样的事情。
有什么建议吗?
--用于Phil的评论
我试图为client和bandinfo创建备份变量,这些变量将保存在VM使用的类中。我把我的类写成IDisposable,这样当我完成我的包装器时,我就可以处理这两个类。老实说,我可能用错了。
MicrosoftBand.MicrosoftBandClient = BandClientManager.Instance.ConnectAsync(pairedBands[0]).Result;这就是我想要调用的,让它成为一个同步调用,因为我想在构造函数中调用bandinfo和client,然后保持这两者直到类被销毁,并在需要时调用var。
我的虚拟机具有:
public BandInformation MicrosoftBand
{
get { return _microsoftBand; }
set { Set(() => MicrosoftBand, ref _microsoftBand, value); }
}如果它们没有在构造函数中传递bandclient,我将使用:
private async Task InitBand(IBandInfo bandInfo)
{
if (bandInfo == null)
{
var allBands = await BandClientManager.Instance.GetBandsAsync();
if (allBands.Length > 0)
{
bandInfo = allBands[0];
}
}
var bandClient = await BandClientManager.Instance.ConnectAsync(bandInfo);
MicrosoftBandInfo = bandInfo;
MicrosoftBandClient = bandClient;
if (MicrosoftBandClient == null)
{
AddErrorMessage("This sample app requires a Microsoft Band paired to your device.Also make sure that you have the latest firmware installed on your Band, as provided by the latest Microsoft Health app.");
}
}这看起来和BandInfo一起工作很好。我得到了一个看起来像工作对象的可靠的客户端,我得到了“线程退出”,没有其他的东西。
注意:我在一个try catch的一次性版本中使用了它,也没有抛出任何异常。
我假设您可以像处理任何其他IDisposable一样处理自己的问题。
我可以每次重新实例化bandclient,只是认为我需要在某个时候分离事件,这意味着我必须保持对BandClient的控制。我可以一直保存到完成,每次都会根据需要添加和删除事件。
发布于 2016-01-10 10:14:42
在VM构造函数中对.Result的阻塞调用很可能是导致挂起的原因。IBandClientManager.ConnectAsync()可以隐式地显示UI (一个Windows Runtime对话框,要求用户确认她想要使用那个特定的蓝牙设备)。如果在UI线程试图显示UI时阻塞了UI线程,那么您现在就陷入了死锁。
调用Task.Result几乎从来都不是一个好主意,更不用说在构造函数中这样做了,因为您几乎不知道构造函数正在执行哪个线程。如果您正在使用异步API (如Band SDK),那么您最好的办法就是将该交互也保持为异步的。相反,将调用ConnectAsync()推迟到实际需要时,并从VM中的异步方法执行此操作。(无论如何,推迟连接都是一个好主意,因为您希望最小化连接到Band的时间,以保护电池寿命。)然后尽早调用Dispose()来关闭蓝牙连接。
发布于 2016-01-10 17:39:55
所以我去看了一堆例子。最后,我登上了MSDN站点上的GravityHeroUAP演示。https://msdn.microsoft.com/en-us/magazine/mt573717.aspx?f=255&MSPPError=-2147217396
我看了他的代码和源代码:https://github.com/kevinash/GravityHeroUWP,他基本上是在做我想做的事情。
然而,我注意到了一些奇怪的事情。在他的视图模型中,一切都是静态的!
public static IBandInfo SelectedBand
{
get { return BandModel._selectedBand; }
set { BandModel._selectedBand = value; }
}
private static IBandClient _bandClient;
public static IBandClient BandClient
{
get { return _bandClient; }
set
{
_bandClient = value;
}
}我最终复制了这个模式(尽管在这个过程中我不得不丢弃了我最喜欢的MVVM库,尽管我确信我可以找回它)。
我在VM中的常见模式:
public string ExceptionOnStart {
get { return _exceptionOnStart; }
set { Set(() => ExceptionOnStart, ref _exceptionOnStart, value); }
}它现在似乎可以工作了!
而且我得到数据的速度太快了
await Windows.Storage.FileIO.AppendLinesAsync(dataFile, new List<string> { toWrite });谢谢你的帮助,Phil,它让我找到了正确的方向!非常非常感谢你。在这上面花了很长时间。标记
https://stackoverflow.com/questions/34700028
复制相似问题