这是windows phone 8.1 silverlight app。 我有一个文件关联。为此,我有一个班级
class AssociationUriMapper : UriMapperBase
{
public override Uri MapUri(Uri uri)
{
//here I'm getting file ID etc..
}
// here I want to read the file content & determine the file type because,
// the case is, even same file extension can contain different type of data
switch (fileType)
{
//here I'm calling appropriate page according to type
}
}
现在问题是MapUri是重写方法,所以它必须有一个返回类型。而OpenStreamForReadAsync()是一种异步方法。我尝试了Wait()方法,创建了新任务&然后在其中调用Start(),Wait()但没有成功。目前我的代码是,
class AssociationUriMapper : UriMapperBase
{
string strData = "";
public override Uri MapUri(Uri uri)
{
strUri = uri.ToString();
// File association launch
if (strUri.Contains("/FileTypeAssociation"))
{
// Get the file ID (after "fileToken=").
int nFileIDIndex = strUri.IndexOf("fileToken=") + 10;
string strFileID = strUri.Substring(nFileIDIndex);
string strFileName = SharedStorageAccessManager.GetSharedFileName(strFileID);
string strIncomingFileType = Path.GetExtension(strFileName);
fnCopyToLocalFolderAndReadContents(strFileID);
switch (fileType)
{
case ".gmm":
//determine if gmm is text
if (objGMM.fnGetGMMType() == GMMFILETYPE.TXT)
{
return new Uri("/PageReadText.xaml?data=" + strData, UriKind.Relative);
}
break;
}
}
}
async void fnCopyToLocalFolderAndReadContents(string strIncomingFileId)
{
StorageFolder objLocalFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
objFile = await SharedStorageAccessManager.CopySharedFileAsync(objLocalFolder, TEMP.gmm, NameCollisionOption.ReplaceExisting, strIncomingFileId);
using (StreamReader streamReader = new StreamReader(objFile))
{
strData = streamReader.ReadToEnd();
}
}
}
答案 0 :(得分:2)
我要做的第一件事就是改变逻辑。当操作系统询问您的应用是否支持Uri映射时,它会立即回答;它不希望应用程序复制和读取文件。通常,Uri映射是非常恒定的;应用程序要么始终支持一个,要么不支持。
所以,我要做的第一件事是在启动时加载所有映射文件,然后创建包含所有结果的AssociationUriMapper
。如果这是不可能的,那么你几乎肯定会使用Uri映射来处理错误的事情。它们不应该是动态的,操作系统很可能假设它们不是动态的。
那就是说,如果你想让它工作,我认为最干净的解决方案是将异步文件操作推送到另一个线程,然后阻止它:
public override Uri MapUri(Uri uri)
{
strUri = uri.ToString();
// File association launch
if (strUri.Contains("/FileTypeAssociation"))
{
// Get the file ID (after "fileToken=").
int nFileIDIndex = strUri.IndexOf("fileToken=") + 10;
string strFileID = strUri.Substring(nFileIDIndex);
string strFileName = SharedStorageAccessManager.GetSharedFileName(strFileID);
string strIncomingFileType = Path.GetExtension(strFileName);
var strData = Task.Run(() => CopyToLocalFolderAndReadContents(strFileID)).GetAwaiter().GetResult();
switch (fileType)
{
case ".gmm":
//determine if gmm is text
if (objGMM.fnGetGMMType() == GMMFILETYPE.TXT)
{
return new Uri("/PageReadText.xaml?data=" + strData, UriKind.Relative);
}
break;
}
}
}
async Task<string> CopyToLocalFolderAndReadContentsAsync(string strIncomingFileId)
{
StorageFolder objLocalFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
objFile = await SharedStorageAccessManager.CopySharedFileAsync(objLocalFolder, TEMP.gmm, NameCollisionOption.ReplaceExisting, strIncomingFileId);
using (StreamReader streamReader = new StreamReader(objFile))
{
return streamReader.ReadToEnd();
}
}
答案 1 :(得分:0)
我不太喜欢它,因为它涉及同步调用异步方法的代码。但以下情况应该有效:
class AssociationUriMapper : UriMapperBase
{
public override Uri MapUri(Uri uri)
{
strUri = uri.ToString();
// File association launch
if (strUri.Contains("/FileTypeAssociation"))
{
// Get the file ID (after "fileToken=").
int nFileIDIndex = strUri.IndexOf("fileToken=") + 10;
string strFileID = strUri.Substring(nFileIDIndex);
string strFileName = SharedStorageAccessManager.GetSharedFileName(strFileID);
string strIncomingFileType = Path.GetExtension(strFileName);
string strData = fnCopyToLocalFolderAndReadContents(strFileID).Result;
switch (fileType)
{
case ".gmm":
//determine if gmm is text
if (objGMM.fnGetGMMType() == GMMFILETYPE.TXT)
{
return new Uri("/PageReadText.xaml?data=" + strData, UriKind.Relative);
}
break;
}
}
}
async Task<string> fnCopyToLocalFolderAndReadContents(string strIncomingFileId)
{
StorageFolder objLocalFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
objFile = await SharedStorageAccessManager.CopySharedFileAsync(objLocalFolder, TEMP.gmm, NameCollisionOption.ReplaceExisting, strIncomingFileId).ConfigureAwait(false);
using (StreamReader streamReader = new StreamReader(objFile))
{
return streamReader.ReadToEnd();
}
}
}
对我来说,一个更大的问题是为什么你要实现像MapUri()
这样的方法,这样它需要调用异步方法,并涉及这种潜在的耗时I / O.我的意思是,也许这实际上是必需的,但它似乎有点偏。不幸的是,问题中没有足够的背景让我觉得我可以提供其他选择。
答案 2 :(得分:0)
不幸的是,没有&#34;漂亮的方式&#34;覆盖非异步方法。
您可以做的最好的事情是确保在异步调用中添加ConfigureAwait(false)
以确保SynchronizationContext
没有流动和死锁,然后访问Result
属性返回的Task
。
我要做的是更改读取文件的方法以返回Task<string>
:
async Task<string> CopyToLocalFolderAndReadContents(string strIncomingFileId)
{
StorageFolder objLocalFolder = Windows.Storage.ApplicationData.Current
.LocalFolder;
objFile = await SharedStorageAccessManager
.CopySharedFileAsync(objLocalFolder, TEMP.gmm,
NameCollisionOption.ReplaceExisting,
strIncomingFileId)
.AsTask().ConfigureAwait(false);
using (StreamReader streamReader = new StreamReader
(await objFile.OpenStreamForReadAsync().ConfigureAwait(false)))
{
return await streamReader.ReadToEndAsync().ConfigureAwait(false);
}
}
然后将呼叫站点更改为:
string data = CopyToLocalFolderAndReadContents(strFileID).Result;