重新想象 Windows 8 Store Apps (66) - 后台任务: 下载和上传
作者:webabcd
介绍
重新想象 Windows 8 Store Apps 之 后台任务
- 后台下载任务
- 后台上传任务
示例
扩展了 DownloadOperation 和 UploadOperation,以便下载进度或上传进度可通知
BackgroundTask/TransferModel.cs
/*
* 扩展了 DownloadOperation 和 UploadOperation,以便下载进度或上传进度可通知
*/ using System;
using System.ComponentModel;
using Windows.Networking.BackgroundTransfer; namespace XamlDemo.BackgroundTask
{
public class TransferModel : INotifyPropertyChanged
{
public DownloadOperation DownloadOperation { get; set; }
public UploadOperation UploadOperation { get; set; } public string Source { get; set; }
public string Destination { get; set; } private string _progress;
public string Progress
{
get { return _progress; }
set
{
_progress = value;
RaisePropertyChanged("Progress");
}
} public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
}
1、演示后台下载任务的应用
BackgroundTask/TransferDownload.xaml
<Page
x:Class="XamlDemo.BackgroundTask.TransferDownload"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:XamlDemo.BackgroundTask"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> <Grid Background="Transparent">
<StackPanel Margin="120 0 0 0"> <ScrollViewer Height="100">
<TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap" />
</ScrollViewer> <Button Name="btnAddDownload" Content="新增一个下载任务" Margin="0 10 0 0" Click="btnAddDownload_Click" />
<Button Name="btnPause" Content="暂停所有下载任务" Margin="0 10 0 0" Click="btnPause_Click" />
<Button Name="btnResume" Content="继续所有下载任务" Margin="0 10 0 0" Click="btnResume_Click" />
<Button Name="btnCancel" Content="取消所有下载任务" Margin="0 10 0 0" Click="btnCancel_Click" /> <ListView Name="listView" Padding="0 10 0 0" Height="300">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0 5" Background="Blue">
<TextBlock Text="{Binding Source}" Margin="5" />
<TextBlock Text="{Binding Destination}" Margin="5" />
<TextBlock Text="{Binding Progress}" Margin="5" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView> </StackPanel>
</Grid>
</Page>
BackgroundTask/TransferDownload.xaml.cs
/*
* 演示后台下载任务的应用
*
* BackgroundDownloader - 后台下载任务管理器
* CostPolicy - 下载的成本策略,BackgroundTransferCostPolicy 枚举
* Default - 允许在高成本(比如 2G 3G)网络上传输(默认值)
* UnrestrictedOnly - 不允许在高成本(比如 2G 3G)网络上传输
* Always - 无论如何均可传输,即使在漫游时
* ServerCredential - 与服务端通信时的凭据
* ProxyCredential - 使用代理时的身份凭据
* SetRequestHeader(string headerName, string headerValue) - 设置 http 请求头
* CreateDownload(Uri uri, IStorageFile resultFile) - 创建一个下载任务,返回 DownloadOperation 对象
* Group - 用于分组下载任务
* static GetCurrentDownloadsAsync(string group) - 获取指定组下的所有下载任务
* static GetCurrentDownloadsAsync() - 获取未与组关联的所有下载任务
*
* DownloadOperation - 下载任务对象
* CostPolicy - 下载的成本策略,BackgroundTransferCostPolicy 枚举
* Group - 获取此下载任务的所属组
* Guid - 获取此下载任务的标识
* RequestedUri - 下载的源 URI
* ResultFile - 下载的目标文件
* GetResponseInformation() - 下载完成后获取到的服务端响应信息,返回 ResponseInformation 对象
* ActualUri - 下载源的真实 URI
* Headers - 服务端响应的 HTTP 头
* StatusCode - 服务端响应的状态码
* Pause() - 暂停此任务
* Resume() - 继续此任务
* StartAsync() - 新增一个下载任务,返回 IAsyncOperationWithProgress<DownloadOperation, DownloadOperation> 对象
* AttachAsync() - 监视已存在的下载任务,返回 IAsyncOperationWithProgress<DownloadOperation, DownloadOperation> 对象
* Progress - 获取下载进度,返回 BackgroundDownloadProgress 对象
*
* BackgroundDownloadProgress - 后台下载任务的下载进度对象
* BytesReceived - 已下载的字节数
* TotalBytesToReceive - 总共需要下载的字节数,未知则为 0
* Status - 下载状态,BackgroundTransferStatus 枚举
* Idle, Running, PausedByApplication, PausedCostedNetwork, PausedNoNetwork, Completed, Canceled, Error
* HasResponseChanged - 服务端响应了则为 true
* HasRestarted - 当下载连接断掉后,系统会通过 http range 头向服务端请求断点续传,如果服务端不支持断点续传则需要重新下载,此种情况则为 true
*/ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using Windows.Networking.BackgroundTransfer;
using Windows.Storage;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Web; namespace XamlDemo.BackgroundTask
{
public sealed partial class TransferDownload : Page
{
// 下载任务的集合
private ObservableCollection<TransferModel> _transfers = new ObservableCollection<TransferModel>(); // 所有下载任务的关联的 CancellationTokenSource 对象
private CancellationTokenSource _cancelToken = new CancellationTokenSource(); public TransferDownload()
{
this.InitializeComponent(); Init();
} private async void Init()
{
listView.ItemsSource = _transfers; // 获取全部下载任务
await LoadDownloadAsync();
} // 加载全部下载任务
private async Task LoadDownloadAsync()
{
IReadOnlyList<DownloadOperation> downloads = null;
try
{
// 获取所有后台下载任务
downloads = await BackgroundDownloader.GetCurrentDownloadsAsync();
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
return;
} if (downloads.Count > )
{
List<Task> tasks = new List<Task>();
foreach (DownloadOperation download in downloads)
{
// 监视指定的后台下载任务
tasks.Add(HandleDownloadAsync(download, false));
} await Task.WhenAll(tasks);
}
} // 新增一个下载任务
private async void btnAddDownload_Click(object sender, RoutedEventArgs e)
{
// 下载地址(注意需要在 Package.appxmanifest 中增加对 .rar 类型文件的关联)
Uri sourceUri = new Uri("http://files.cnblogs.com/webabcd/Windows8.rar", UriKind.Absolute); StorageFile destinationFile;
try
{
// 保存的目标地址
destinationFile = await KnownFolders.DocumentsLibrary.CreateFileAsync("Windows8.rar", CreationCollisionOption.GenerateUniqueName);
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
return;
} // 创建一个后台下载任务
BackgroundDownloader backgroundDownloader = new BackgroundDownloader();
DownloadOperation download = backgroundDownloader.CreateDownload(sourceUri, destinationFile); // 监视指定的后台下载任务
await HandleDownloadAsync(download, true);
} /// <summary>
/// 监视指定的后台下载任务
/// </summary>
/// <param name="download">后台下载任务</param>
/// <param name="isNew">是否是新增的任务</param>
private async Task HandleDownloadAsync(DownloadOperation download, bool isNew)
{
try
{
// 将 DownloadOperation 附加到 TransferModel,以便下载进度可通知
TransferModel transfer = new TransferModel();
transfer.DownloadOperation = download;
transfer.Source = download.RequestedUri.ToString();
transfer.Destination = download.ResultFile.Path;
transfer.Progress = "0 / 0"; _transfers.Add(transfer); lblMsg.Text += "Task Count: " + _transfers.Count.ToString();
lblMsg.Text += Environment.NewLine; // 当下载进度发生变化时的回调函数
Progress<DownloadOperation> progressCallback = new Progress<DownloadOperation>(DownloadProgress); if (isNew)
await download.StartAsync().AsTask(_cancelToken.Token, progressCallback); // 新增一个后台下载任务
else
await download.AttachAsync().AsTask(_cancelToken.Token, progressCallback); // 监视已存在的后台下载任务 // 下载完成后获取服务端的响应信息
ResponseInformation response = download.GetResponseInformation();
lblMsg.Text += "Completed: " + response.ActualUri + "-" + response.StatusCode.ToString();
lblMsg.Text += Environment.NewLine;
}
catch (TaskCanceledException) // 调用 CancellationTokenSource.Cancel() 后会抛出此异常
{
lblMsg.Text += "Canceled: " + download.Guid;
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
// 将异常转换为 WebErrorStatus 枚举,如果获取到的是 WebErrorStatus.Unknown 则说明此次异常不是涉及 web 的异常
WebErrorStatus error = BackgroundTransferError.GetStatus(ex.HResult); lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
finally
{
_transfers.Remove(_transfers.First(p => p.DownloadOperation == download));
}
} // 进度发生变化时,更新 TransferModel 的 Progress,以便通知
private void DownloadProgress(DownloadOperation download)
{
TransferModel transfer = _transfers.First(p => p.DownloadOperation == download);
transfer.Progress = download.Progress.BytesReceived.ToString("#,0") + " / " + download.Progress.TotalBytesToReceive.ToString("#,0");
} // 暂停全部后台下载任务
private void btnPause_Click(object sender, RoutedEventArgs e)
{
lblMsg.Text += "All Paused";
lblMsg.Text += Environment.NewLine;
foreach (TransferModel transfer in _transfers)
{
if (transfer.DownloadOperation.Progress.Status == BackgroundTransferStatus.Running)
{
transfer.DownloadOperation.Pause();
}
}
} // 继续全部后台下载任务
private void btnResume_Click(object sender, RoutedEventArgs e)
{
lblMsg.Text += "All Resumed";
lblMsg.Text += Environment.NewLine;
foreach (TransferModel transfer in _transfers)
{
if (transfer.DownloadOperation.Progress.Status == BackgroundTransferStatus.PausedByApplication)
{
transfer.DownloadOperation.Resume();
}
}
} // 取消全部后台下载任务
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
_cancelToken.Cancel();
_cancelToken.Dispose(); _cancelToken = new CancellationTokenSource();
}
}
}
2、演示后台上传任务的应用
BackgroundTask/TransferUpload.xaml
<Page
x:Class="XamlDemo.BackgroundTask.TransferUpload"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:XamlDemo.BackgroundTask"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> <Grid Background="Transparent">
<StackPanel Margin="120 0 0 0"> <ScrollViewer Height="100">
<TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap" />
</ScrollViewer> <Button Name="btnAddUpload" Content="新增一个上传任务(一次请求上传一个文件)" Margin="0 10 0 0" Click="btnAddUpload_Click" />
<Button Name="btnAddMultiUpload" Content="新增一个上传任务(一次请求上传多个文件)" Margin="0 10 0 0" Click="btnAddMultiUpload_Click" />
<Button Name="btnCancel" Content="取消所有上传任务" Margin="0 10 0 0" Click="btnCancel_Click" /> <ListView Name="listView" Padding="0 10 0 0" Height="300">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0 5" Background="Blue">
<TextBlock Text="{Binding Source}" Margin="5" />
<TextBlock Text="{Binding Destination}" Margin="5" />
<TextBlock Text="{Binding Progress}" Margin="5" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView> </StackPanel>
</Grid>
</Page>
BackgroundTask/TransferUpload.xaml.cs
/*
* 演示后台上传任务的应用
*
* BackgroundUploader - 后台上传任务管理器
* CostPolicy - 上传的成本策略,BackgroundTransferCostPolicy 枚举
* Default - 不允许在高成本(比如 2G 3G)网络上传输
* UnrestrictedOnly - 允许在高成本(比如 2G 3G)网络上传输
* Always - 无论如何均可传输,即使在漫游时
* ServerCredential - 与服务端通信时的凭据
* ProxyCredential - 使用代理时的身份凭据
* SetRequestHeader(string headerName, string headerValue) - 设置 http 请求头
* CreateUpload(Uri uri, IStorageFile sourceFile) - 创建一个上传任务,返回 UploadOperation 对象
* CreateUploadFromStreamAsync(Uri uri, IInputStream sourceStream) - 以流的方式创建一个上传任务
* CreateUploadAsync(Uri uri, IEnumerable<BackgroundTransferContentPart> parts) - 创建一个包含多个上传文件的上传任务
* Group - 用于分组上传任务
* static GetCurrentUploadsAsync(string group) - 获取指定组下的所有上传任务
* static GetCurrentUploadsAsync() - 获取未与组关联的所有上传任务
*
* UploadOperation - 上传任务对象
* CostPolicy - 上传的成本策略,BackgroundTransferCostPolicy 枚举
* Group - 获取此上传任务的所属组
* Guid - 获取此上传任务的标识
* RequestedUri - 上传任务所请求的服务端地址
* SourceFile - 需要上传的文件,如果是一次上传多个文件则此属性为 null
* GetResponseInformation() - 上传完成后获取到的服务端响应信息,返回 ResponseInformation 对象
* ActualUri - 上传服务的真实 URI
* Headers - 服务端响应的 HTTP 头
* StatusCode - 服务端响应的状态码
* StartAsync() - 新增一个上传任务,返回 IAsyncOperationWithProgress<UploadOperation, UploadOperation> 对象
* AttachAsync() - 监视已存在的上传任务,返回 IAsyncOperationWithProgress<UploadOperation, UploadOperation> 对象
* Progress - 获取上传进度,返回 BackgroundUploadProgress 对象
*
* BackgroundUploadProgress - 后台上传任务的上传进度对象
* BytesSent - 已上传的字节数
* TotalBytesToSend - 总共需要上传的字节数
* Status - 上传状态,BackgroundTransferStatus 枚举
* Idle, Running, PausedByApplication, PausedCostedNetwork, PausedNoNetwork, Completed, Canceled, Error
* HasResponseChanged - 服务端响应了则为 true
* HasRestarted - 当上传连接断掉后,系统会重新上传,此种情况则为 true
*/ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Windows.Networking.BackgroundTransfer;
using Windows.Storage;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Web; namespace XamlDemo.BackgroundTask
{
public sealed partial class TransferUpload : Page
{
// 上传任务的集合
private ObservableCollection<TransferModel> _transfers = new ObservableCollection<TransferModel>(); // 所有上传任务的关联的 CancellationTokenSource 对象
private CancellationTokenSource _cancelToken = new CancellationTokenSource(); public TransferUpload()
{
this.InitializeComponent(); Init();
} private async void Init()
{
listView.ItemsSource = _transfers; // 获取全部上传任务
await LoadUploadAsync();
} // 加载全部上传任务
private async Task LoadUploadAsync()
{
IReadOnlyList<UploadOperation> uploads = null;
try
{
// 获取所有后台上传任务
uploads = await BackgroundUploader.GetCurrentUploadsAsync();
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
return;
} if (uploads.Count > )
{
List<Task> tasks = new List<Task>();
foreach (UploadOperation upload in uploads)
{
// 监视指定的后台上传任务
tasks.Add(HandleUploadAsync(upload, false));
} await Task.WhenAll(tasks);
}
} // 新增一个上传任务(一次请求上传一个文件)
private async void btnAddUpload_Click(object sender, RoutedEventArgs e)
{
// 上传服务的地址
Uri serverUri = new Uri("http://localhost:39629/UploadFile.aspx", UriKind.Absolute); StorageFile sourceFile;
try
{
// 文件源
sourceFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Logo.png", UriKind.Absolute));
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
return;
} // 实例化 BackgroundUploader,并设置 http header
BackgroundUploader backgroundUploader = new BackgroundUploader();
backgroundUploader.SetRequestHeader("Filename", "Logo.png"); // 创建一个后台上传任务,此任务包含一个上传文件
UploadOperation upload = backgroundUploader.CreateUpload(serverUri, sourceFile); // 以流的方式创建一个后台上传任务
// await backgroundUploader.CreateUploadFromStreamAsync(Uri uri, IInputStream sourceStream); // 监视指定的后台上传任务
await HandleUploadAsync(upload, true);
} // 新增一个上传任务(一次请求上传多个文件)
private async void btnAddMultiUpload_Click(object sender, RoutedEventArgs e)
{
// 上传服务的地址
Uri serverUri = new Uri("http://localhost:39629/UploadFile.aspx", UriKind.Absolute); // 需要上传的文件源集合
List<StorageFile> sourceFiles = new List<StorageFile>();
for (int i = ; i < ; i++)
{
StorageFile sourceFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Logo.png", UriKind.Absolute));
sourceFiles.Add(sourceFile);
} // 构造需要上传 BackgroundTransferContentPart 集合
List<BackgroundTransferContentPart> contentParts = new List<BackgroundTransferContentPart>();
for (int i = ; i < sourceFiles.Count; i++)
{
BackgroundTransferContentPart contentPart = new BackgroundTransferContentPart("File" + i, sourceFiles[i].Name);
contentPart.SetFile(sourceFiles[i]);
contentParts.Add(contentPart);
} // 创建一个后台上传任务,此任务包含多个上传文件
BackgroundUploader backgroundUploader = new BackgroundUploader();
UploadOperation upload = await backgroundUploader.CreateUploadAsync(serverUri, contentParts); // 监视指定的后台上传任务
await HandleUploadAsync(upload, true);
} /// <summary>
/// 监视指定的后台上传任务
/// </summary>
/// <param name="upload">后台上传任务</param>
/// <param name="isNew">是否是新增的任务</param>
private async Task HandleUploadAsync(UploadOperation upload, bool isNew)
{
try
{
// 将 UploadOperation 附加到 TransferModel,以便上传进度可通知
TransferModel transfer = new TransferModel();
transfer.UploadOperation = upload;
transfer.Source = "多个文件";
transfer.Destination = upload.RequestedUri.ToString();
transfer.Progress = "0 / 0"; _transfers.Add(transfer); lblMsg.Text += "Task Count: " + _transfers.Count.ToString();
lblMsg.Text += Environment.NewLine; // 当上传进度发生变化时的回调函数
Progress<UploadOperation> progressCallback = new Progress<UploadOperation>(UploadProgress); if (isNew)
await upload.StartAsync().AsTask(_cancelToken.Token, progressCallback); // 新增一个后台上传任务
else
await upload.AttachAsync().AsTask(_cancelToken.Token, progressCallback); // 监视已存在的后台上传任务 // 上传完成后获取服务端的响应信息
ResponseInformation response = upload.GetResponseInformation();
lblMsg.Text += "Completed: " + response.ActualUri + "-" + response.StatusCode.ToString();
lblMsg.Text += Environment.NewLine;
}
catch (TaskCanceledException) // 调用 CancellationTokenSource.Cancel() 后会抛出此异常
{
lblMsg.Text += "Canceled: " + upload.Guid;
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
// 将异常转换为 WebErrorStatus 枚举,如果获取到的是 WebErrorStatus.Unknown 则说明此次异常不是涉及 web 的异常
WebErrorStatus error = BackgroundTransferError.GetStatus(ex.HResult); lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
finally
{
_transfers.Remove(_transfers.First(p => p.UploadOperation == upload));
}
} // 进度发生变化时,更新 TransferModel 的 Progress,以便通知
private void UploadProgress(UploadOperation upload)
{
TransferModel transfer = _transfers.First(p => p.UploadOperation == upload);
transfer.Progress = upload.Progress.BytesSent.ToString("#,0") + " / " + upload.Progress.TotalBytesToSend.ToString("#,0");
} // 取消全部后台上传任务
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
_cancelToken.Cancel();
_cancelToken.Dispose(); _cancelToken = new CancellationTokenSource();
}
}
}
用于接收上传文件的服务
WebServer/UploadFile.aspx.cs
/*
* 用于接收上传文件的服务
*/ using System;
using System.IO; namespace WebServer
{
public partial class UploadFile : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
try
{
if (Request.Headers["Filename"] != null)
{
// 接收单个文件,并保存
string fileName = Request.Headers["Filename"];
string saveLocation = Server.MapPath("UploadFiles") + "\\" + fileName.Insert(fileName.IndexOf("."), "_" + Guid.NewGuid().ToString());
using (System.IO.FileStream fs = new System.IO.FileStream(saveLocation, FileMode.Create))
{
Request.InputStream.CopyTo(fs);
}
}
else
{
// 接收多个文件,并保存
for (int i = ; i < Request.Files.Count; i++)
{
var file = Request.Files[i];
if (file.ContentLength > )
{
string fileName = System.IO.Path.GetFileName(file.FileName);
string saveLocation = Server.MapPath("UploadFiles") + "\\" + fileName.Insert(fileName.IndexOf("."), "_" + Guid.NewGuid().ToString());
file.SaveAs(saveLocation);
}
}
}
}
catch (Exception ex)
{
Trace.Write(ex.Message);
Response.StatusCode = ;
Response.StatusDescription = ex.Message;
Response.End();
}
}
}
}
OK
[源码下载]
重新想象 Windows 8 Store Apps (66) - 后台任务: 下载和上传的更多相关文章
- 重新想象 Windows 8 Store Apps (64) - 后台任务: 开发一个简单的后台任务
[源码下载] 重新想象 Windows 8 Store Apps (64) - 后台任务: 开发一个简单的后台任务 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后 ...
- 重新想象 Windows 8 Store Apps (65) - 后台任务: 音乐的后台播放和控制
[源码下载] 重新想象 Windows 8 Store Apps (65) - 后台任务: 音乐的后台播放和控制 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后台 ...
- 重新想象 Windows 8 Store Apps (67) - 后台任务: 推送通知
[源码下载] 重新想象 Windows 8 Store Apps (67) - 后台任务: 推送通知 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后台任务 推送通 ...
- 重新想象 Windows 8 Store Apps (68) - 后台任务: 控制通道(ControlChannel)
[源码下载] 重新想象 Windows 8 Store Apps (68) - 后台任务: 控制通道(ControlChannel) 作者:webabcd 介绍重新想象 Windows 8 Store ...
- 重新想象 Windows 8 Store Apps 系列文章索引
[源码下载][重新想象 Windows 8.1 Store Apps 系列文章] 重新想象 Windows 8 Store Apps 系列文章索引 作者:webabcd 1.重新想象 Windows ...
- 重新想象 Windows 8 Store Apps (48) - 多线程之其他辅助类: SpinWait, SpinLock, Volatile, SynchronizationContext, CoreDispatcher, ThreadLocal, ThreadStaticAttribute
[源码下载] 重新想象 Windows 8 Store Apps (48) - 多线程之其他辅助类: SpinWait, SpinLock, Volatile, SynchronizationCont ...
- 重新想象 Windows 8 Store Apps (59) - 锁屏
[源码下载] 重新想象 Windows 8 Store Apps (59) - 锁屏 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 锁屏 登录锁屏,获取当前程序的锁 ...
- 重新想象 Windows 8 Store Apps (61) - 通信: http, oauth
[源码下载] 重新想象 Windows 8 Store Apps (61) - 通信: http, oauth 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 通信 ...
- 重新想象 Windows 8 Store Apps (32) - 加密解密: 非对称算法, 数据转换的辅助类
原文:重新想象 Windows 8 Store Apps (32) - 加密解密: 非对称算法, 数据转换的辅助类 [源码下载] 重新想象 Windows 8 Store Apps (32) - 加密 ...
随机推荐
- UnionPay,ChinaPay 最新 银联支付接口C#\Asp.net\MVC 版本
1.概念普及 一.理解什么是UnionPay.ChinaPay 这两个概念如果搞不清楚,绝对够你瞎折腾一段时间的. UnionPay:中国银联,最大的机构:他本身也提供系统接口但都是B2B的,对于单个 ...
- win10初体验,我的错误代码哪里去了
今天闲着,就把WIN7升级安装成WIN10,感觉这次WIN10的升级方案确实还可以人,可以保留文件和配置升级. 升级完,试了一下宽带连接,发现错误代码没了,像下面的应该就691呢~~~
- cordova plugin数据传递概要
cordova plugin数据传递概要: 1.调用pluginManager向所有插件发送消息: PluginManager.postMessage(String id, Object data); ...
- 老鼠跑猫叫主人惊醒c++观察者模式实现
这个题目算是比较经典的观察者模式了,老鼠作为一个Subject,主动发出跑的动作,紧跟着猫由于老鼠的跑而发出叫声,主人也被惊醒,在这里猫跟主人都是被动的,是观察者角色,代码实现如下: class CS ...
- postgresql 获取刚刚插入的数据主键id
postgresql不支持last_insert_id()方法,恶心到啦: 不过还好它有其他的解决方案: 创建一个测试数据表: CREATE TABLE test.test18 ( id serial ...
- Android开发在路上:少去踩坑,多走捷径
转自:http://djt.qq.com/article/view/1193 最近一朋友提了几个Android问题让我帮忙写个小分享,我觉得对新人还是挺有帮助的,所以有了这个小分享. 1.目前, ...
- Linux进程通信 之 信号灯(semphore)(System V && POSIX)
一. 信号灯简介 信号灯与其他进程间通信方式不大相同,它主要提供对进程间共享资源访问控制机制. 相当于内存中的标志,进程可以根据它判定是否能够访问某些共享资源,同时,进程 也可以修改该标志.除了用于访 ...
- mac 进程管理
1.前言 启用goagent.firefly等服务的时候,如果非正常退出,再次启动经常会遇到address already in use,端口被先前启动的服务进程所占用,导致服务无法使用.这种情况,可 ...
- Shell之数学计算
本博客已经迁往http://www.kemaswill.com/, 博客园这边也会继续更新, 欢迎关注~ 数学计算是Shell中比较常用的一种操作, 但是因为shell中所有的变量都默认为字符串, ...
- python 字符串复制
通过变量来进行赋值 fstr = 'strcpy'sstr = fstrfstr = 'strcpy2'print sstr