
<Window x:Class="Blogs.Tools.Gather.MultiGatherWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:FYJ.Winui.Controls;assembly=FYJ.Winui"
xmlns:util="clr-namespace:Blogs.Tools.Util"
Title="文章批量采集工具" Height="550" Width="880">
<Window.Resources>
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"></Setter>
</Style>
<Style TargetType="c:TextBoxEx">
<Setter Property="Height" Value="24"></Setter>
</Style>
<Style TargetType="c:ComboBoxEx">
<Setter Property="Height" Value="24"></Setter>
</Style>
<Style TargetType="c:CheckBoxEx">
<Setter Property="VerticalAlignment" Value="Center"></Setter>
</Style>
<util:ReverseConverter x:Key="ReverseConverter1"></util:ReverseConverter>
</Window.Resources>
<DockPanel >
<Menu DockPanel.Dock="Top">
<MenuItem Header="文件(F)"></MenuItem>
<MenuItem Header="工具(T)">
<MenuItem Header="选项"></MenuItem>
</MenuItem>
<MenuItem Header="帮助(H)"></MenuItem>
</Menu>
<ToolBarPanel DockPanel.Dock="Top">
<ToolBar ToolBar.OverflowMode="Never">
<Menu>
<MenuItem Header="开始" Background="AliceBlue" x:Name="btnStart" Click="btnGather_Click"></MenuItem>
<MenuItem Header="结束" Background="Aqua" Margin="10,0,0,0" x:Name="btnStop" IsEnabled="{Binding ElementName=btnStart,Path=IsEnabled,Converter={StaticResource ReverseConverter1}}" Click="btnStop_Click"></MenuItem>
</Menu>
</ToolBar>
</ToolBarPanel>
<StackPanel DockPanel.Dock="Top" Margin="0,20,0,20" >
<WrapPanel>
<TextBlock Text="文章发布类"></TextBlock>
<c:ComboBoxEx Width="300" Margin="10,0,0,0" Height="24" x:Name="cbConfigName" SelectionChanged="cbConfigName_SelectionChanged" ></c:ComboBoxEx>
</WrapPanel>
<WrapPanel Margin="0,10,0,0">
<TextBlock Text="链接字符串" ></TextBlock>
<TextBox Width="610" Margin="10,0,0,0" Height="24" x:Name="txtConnectionString"></TextBox>
<Button Content="测试" Width="60" Height="24" Margin="10,0,0,0" x:Name="btnTest" Click="btnTest_Click"></Button>
</WrapPanel>
<WrapPanel Margin="0,10,0,0">
<TextBlock Text="采集规则" Width="60" ></TextBlock>
<c:ComboBoxEx Width="300" Margin="10,0,0,0" x:Name="comboRule"></c:ComboBoxEx>
<c:CheckBoxEx Content="下载远程图片" Margin="10,0,0,0" Name="checkBox_DownPic"></c:CheckBoxEx>
<c:CheckBoxEx Content="下载远程附件" Margin="10,0,0,0" Name="chk_DownAttachment"></c:CheckBoxEx>
<c:CheckBoxEx Content="是否递归" Margin="10,0,0,0" Name="chk_isRecursive"></c:CheckBoxEx>
</WrapPanel>
<WrapPanel Margin="0,10,0,0">
<TextBlock Text="URL" Width="60" Foreground="#FFF31818"></TextBlock>
<c:TextBoxEx x:Name="txtFromUrl" Width="610" Margin="10,0,0,0" Height="24"/>
</WrapPanel>
<WrapPanel Margin="0,10,0,0">
<TextBlock Text="板块/分类" Width="60"></TextBlock>
<c:ComboBoxEx Width="150" Margin="10,0,0,0" Name="comboBox_category" DropDownOpened="comboBox_category_DropDownOpened"></c:ComboBoxEx>
<TextBlock Text="发布用户ID" Margin="10,0,0,0" Width="60"></TextBlock>
<c:TextBoxEx Text="1" Width="150" Margin="10,0,0,0" Name="txtPostUserID"></c:TextBoxEx>
<TextBlock Text="发布用户名" Margin="10,0,0,0" Width="60"></TextBlock>
<c:TextBoxEx Text="admin" Width="150" Margin="10,0,0,0" Name="txtPostUserName"></c:TextBoxEx>
</WrapPanel>
<WrapPanel Margin="0,10,0,0">
<TextBlock Text="来源" Width="60"></TextBlock>
<c:TextBoxEx Width="150" Margin="10,0,0,0" Name="txtFromSource"></c:TextBoxEx>
<TextBlock Text="作者" Margin="10,0,0,0" Width="60"></TextBlock>
<c:TextBoxEx Text="" Width="150" Margin="10,0,0,0" Name="txtFromAuthor"></c:TextBoxEx>
<TextBlock Text="采集条数:" Width="60" Margin="10,0,0,0"></TextBlock>
<c:TextBoxEx Text="100" Width="150" Margin="10,0,0,0" Name="txtGatherCount"></c:TextBoxEx>
</WrapPanel>
</StackPanel>
<Grid DockPanel.Dock="Bottom">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
</Grid.ColumnDefinitions>
<c:TextBlockEx Text="就绪" Name="txtState" Grid.Column="0"></c:TextBlockEx>
<!--附件上传进度-->
<c:ProgressBarEx Grid.Column="1" Name="attachmentProgress"></c:ProgressBarEx>
<c:ProgressBarEx Grid.Column="2" Margin="10,0,0,0" Name="progressState" ValueChanged="progressState_ValueChanged"></c:ProgressBarEx>
</Grid>
<c:LogListBox x:Name="logList1"></c:LogListBox>
</DockPanel>
<Window.TaskbarItemInfo>
<TaskbarItemInfo x:Name="taskbarItemInfo1">
</TaskbarItemInfo>
</Window.TaskbarItemInfo>
</Window>
配置
<?xml version="1.0" encoding="utf-8" ?>
<GatherTool>
<Gathers>
<Gather id="DisThread" type="Blogs.Tools.Gather.Discuz.DisThread,Blogs.Tools" providerName="MySql.Data.MySqlClient" connectionString="Server=127.0.0.1;Uid=root;Pwd=root;Database=db_ztku;Port=3306;CharSet=utf8;AutoEnlist=false" tablePre="ztku_"></Gather>
</Gathers>
<Analyzes>
<Analyze type="Blogs.Tools.Gather.Analyze.CnblogsAnalyze,Blogs.Tools" pattern="www.cnblogs.com"></Analyze>
<Analyze type="Blogs.Tools.Gather.Analyze.DiscuzAnalyze,Blogs.Tools"></Analyze>
<Analyze type="Blogs.Tools.Gather.Analyze.IT168Analyze,Blogs.Tools" pattern="it168.com"></Analyze>
</Analyzes>
<Rules>
<Rule name="Cnblogs" matchUrl="http://www.cnblogs.com">
<ArticlePatterns>
<ArticlePattern>http://www.cnblogs.com/\w+/p/\d+.html</ArticlePattern>
<ArticlePattern>http://www.cnblogs.com/\w+/archive/\d{4}/\d{2}/\d{2}/.+.html</ArticlePattern>
</ArticlePatterns>
<!--内容分析类-->
<Analyze type="Blogs.Tools.Gather.Analyze.CnblogsAnalyze,Blogs.Tools">
</Analyze>
</Rule>
<Rule name="Admin10000" matchUrl="http://wwww.admin10000.com">
<ArticlePatterns>
<ArticlePattern>/\w+/\d+.html</ArticlePattern>
</ArticlePatterns>
<Analyze type="Blogs.Tools.Gather.Analyze.RegexAnalyze,Blogs.Tools">
<TitlePattern>
<![CDATA[
<title.*?>[\s|\n]*(.*)-\s*WEB开发者[\s|\n]*</title>
]]>
</TitlePattern>
<AuthorPattern>
<![CDATA[
<span class="source">来源:<a\s*href=".*?".+?>(.*?)</a>
]]>
</AuthorPattern>
<FromPattern>
<![CDATA[
<span class="source">来源:<a\s*href="(.*?)".+?>
]]>
</FromPattern>
<ContentPattern>
<![CDATA[
<div class="body textStyle">((.|\n)*?)</div>
]]>
</ContentPattern>
</Analyze>
</Rule>
<Rule name="Discuz">
<ArticlePatterns>
<ArticlePattern>thread-\d+-\d+-\d+.html</ArticlePattern>
</ArticlePatterns>
<!--内容分析类-->
<Analyze type="Blogs.Tools.Gather.Analyze.DiscuzAnalyze,Blogs.Tools">
</Analyze>
</Rule>
<Rule name="IT168" matchUrl="it168.com">
<ArticlePatterns>
<ArticlePattern></ArticlePattern>
</ArticlePatterns>
<!--内容分析类-->
<Analyze type="Blogs.Tools.Gather.Analyze.IT168Analyze,Blogs.Tools">
</Analyze>
</Rule>
</Rules>
<!--自动分析-->
<AutoAnalyzes>
<AutoAnalyze Author="" FromSource="" Title="" Content=""></AutoAnalyze>
</AutoAnalyzes>
</GatherTool>后台CS
using Blogs.Tools.Gather.Analyze;
using Blogs.Tools.Gather.Blog;
using Blogs.Tools.Gather.Common;
using Blogs.Tools.Gather.Discuz;
using Blogs.Tools.Gather.Wordpress;
using FYJ.Upload;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Net;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Shell;
using System.Xml;
using Blogs.Tool.Gather.Common;
using System.Text.RegularExpressions;
namespace Blogs.Tools.Gather
{
/// <summary>
/// MultiGatherWindow.xaml 的交互逻辑
/// </summary>
public partial class MultiGatherWindow : Window
{
public MultiGatherWindow()
{
InitializeComponent();
}
#region 初始化
//同步对象
private object sync = new object();
private CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
//线程数
private const int THREAD_COUNT = 10;
//已采集数
private int gathered = 0;
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
LoadClassConfig();
LoadMuitiAnalyzeConfig();
this.AllowDrop = true;
}
private void LoadClassConfig()
{
List<object> list = new List<object>();
DataSet ds = new DataSet();
ds.ReadXml(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Gather.xml"));
DataTable dt = ds.Tables["Gather"];
foreach (DataRow dr in dt.Rows)
{
FYJ.Data.IDbHelper db = FYJ.Data.DbFactory.CreateIDbHelper(dr["providerName"].ToString(), dr["connectionString"].ToString());
string type = dr["type"].ToString();
IGather gather = (IGather)Activator.CreateInstance(Type.GetType(type));
gather.Db = db;
gather.TablePre = dr["tablePre"].ToString();
gather.ID = dr["id"].ToString();
object extend = dr["extend"];
gather.Extend = (extend == null ? null : extend.ToString());
list.Add(new { Text = dr["id"].ToString(), Value = gather });
}
this.cbConfigName.ItemsSource = list;
this.cbConfigName.SelectedValuePath = "Value";
this.cbConfigName.DisplayMemberPath = "Text";
this.cbConfigName.SelectedIndex = 0;
}
private void LoadMuitiAnalyzeConfig()
{
List<object> list = new List<object>();
XmlDocument doc = new XmlDocument();
doc.Load(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Gather.xml"));
foreach (XmlNode node in doc.GetElementsByTagName("Rule"))
{
GatherRule rule = new GatherRule();
List<string> patterns = new List<string>();
foreach (XmlNode n in node.SelectNodes("ArticlePatterns//ArticlePattern"))
{
patterns.Add(n.InnerText);
}
rule.ArticlePatterns = patterns;
XmlNode analyzeNode = node.SelectSingleNode("Analyze");
string type = analyzeNode.Attributes["type"].InnerText;
IAnalyze analyze = (IAnalyze)Activator.CreateInstance(Type.GetType(type));
if (analyzeNode.SelectSingleNode("TitlePattern") != null)
{
analyze.TitlePattern = analyzeNode.SelectSingleNode("TitlePattern").InnerText.Trim();
}
if (analyzeNode.SelectSingleNode("AuthorPattern") != null)
{
analyze.AuthorPattern = analyzeNode.SelectSingleNode("AuthorPattern").InnerText.Trim();
}
if (analyzeNode.SelectSingleNode("FromPattern") != null)
{
analyze.FromPattern = analyzeNode.SelectSingleNode("FromPattern").InnerText.Trim();
}
if (analyzeNode.SelectSingleNode("ContentPattern") != null)
{
analyze.ContentPattern = analyzeNode.SelectSingleNode("ContentPattern").InnerText.Trim();
}
rule.Analyze = analyze;
list.Add(new { Text = node.Attributes["name"].Value, Value = rule });
}
this.comboRule.ItemsSource = list;
this.comboRule.SelectedValuePath = "Value";
this.comboRule.DisplayMemberPath = "Text";
this.comboRule.SelectedIndex = 0;
}
#endregion
#region 其它操作
private void btnTest_Click(object sender, RoutedEventArgs e)
{
if (cbConfigName.Items.Count > 0)
{
IGather gather = this.cbConfigName.SelectedValue as IGather;
FYJ.Data.IDbHelper db = gather.Db;
if (db.TestCanConnectionOpen())
{
MessageBox.Show("连接成功");
}
else
{
MessageBox.Show("连接失败");
}
}
}
private async void comboBox_category_DropDownOpened(object sender, EventArgs e)
{
if (!String.IsNullOrEmpty(this.cbConfigName.Text))
{
try
{
this.txtState.Text = "正在获取板块/分类列表...";
CateDataSource data = new CateDataSource();
IGather gather = this.cbConfigName.SelectedValue as IGather;
await Task.Factory.StartNew(() =>
{
data = gather.GetCate();
});
this.comboBox_category.ItemsSource = data.DataSource.DefaultView;
this.comboBox_category.DisplayMemberPath = data.DisplayMember;
this.comboBox_category.SelectedValuePath = data.ValueMember;
this.comboBox_category.SelectedIndex = 0;
this.txtState.Text = "就绪";
}
catch (Exception ex)
{
this.txtState.Text = "获取板块错误:" + ex.Message;
}
}
}
private void cbConfigName_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (cbConfigName.Items.Count > 0)
{
this.comboBox_category.ItemsSource = null;
IGather gather = this.cbConfigName.SelectedValue as IGather;
FYJ.Data.IDbHelper db = gather.Db;
this.txtConnectionString.Text = db.ConnectionString;
}
}
#endregion
#region 批量采集
private async void btnGather_Click(object sender, RoutedEventArgs e)
{
if (this.txtFromUrl.Text.Trim() == "")
{
MessageBox.Show("请输入url");
return;
}
if (this.comboBox_category.SelectedIndex == -1)
{
MessageBox.Show("请选择分类");
return;
}
this.btnStart.IsEnabled = false;
this.txtState.Text = "正在分析Url...";
IGather gather = this.cbConfigName.SelectedValue as IGather;
GatherRule rule = this.comboRule.SelectedValue as GatherRule;
int count = Convert.ToInt32(this.txtGatherCount.Text);
this.progressState.Visibility = Visibility.Visible;
string url = this.txtFromUrl.Text.Trim();
this.gathered = 0;
this.progressState.Value = 0;
await Task.Factory.StartNew(() =>
{
Gather(url, count, gather, rule);
});
this.btnStart.IsEnabled = true;
}
#endregion
private void ThreadWork(string url, IGather gather, GatherRule rule)
{
if (cancelTokenSource.IsCancellationRequested)
{
this.logList1.AddErrorItem("线程" + Thread.CurrentThread.ManagedThreadId + "操作已被用户取消");
return;
}
//采集
GatherSingle(Thread.CurrentThread.ManagedThreadId + "", url, gather, rule.Analyze);
}
private void Gather(string url, int count, IGather gather, GatherRule rule)
{
try
{
List<string> urls = rule.GetArticleUrls(url);
if (this.chk_isRecursive.IsChecked == false)
{
this.progressState.Maximum = Math.Min(urls.Count, count);
}
else
{
this.progressState.Maximum = count;
}
count = (int)this.progressState.Maximum;
for (int k = 0; k < urls.Count; )
{
if (gathered < count)
{
List<Task> taskList = new List<Task>();
for (int i = 0; i < THREAD_COUNT && i < urls.Count && k < urls.Count; i++)
{
Task task = new Task(() =>
{
Monitor.Enter(sync);
if (k < urls.Count)
{
string u = urls[k];
k++;
Monitor.Exit(sync);
ThreadWork(u, gather, rule);
}
}, cancelTokenSource.Token);
taskList.Add(task);
task.Start();
gathered++;
}
this.txtState.Text = "正在等待线程完成...";
//等待所有线程完成
Task.WaitAll(taskList.ToArray());
}
}
for (int k = 0; k < urls.Count; k++)
{
//递归
if (gathered < count && this.chk_isRecursive.IsChecked == true)
{
if (urls[k] != url)
{
Gather(urls[k], count, gather, rule);
}
}
}
}
catch (Exception ex)
{
this.logList1.AddErrorItem(ex.Message);
if (!ex.Message.Contains("不能对已完成的任务调用 Start"))
{
//重试
this.logList1.AddItem("重试" + url + "...");
if (gathered < count)
{
Gather(url, count, gather, rule);
}
}
}
this.progressState.Value = this.progressState.Maximum;
this.txtState.Text = "就绪";
}
/// <summary>
///
/// </summary>
/// <param name="url"></param>
/// <param name="gather"></param>
/// <param name="ana"></param>
private void GatherSingle(string threadid, string url, IGather gather, IAnalyze ana)
{
try
{
//Monitor.Enter(sync);
//this.txtState.Text = "线程" + threadid + ":正在发布" + (this.progressState.Value + 1) + "/" + this.progressState.Maximum + "...";
//Monitor.Exit(sync);
if (gather.IsExistFromUrl(url))
{
this.logList1.AddErrorItem("线程" + threadid + ":已存在相同来源Url");
Step();
return;
}
ana.Url = url;
ana.Html = FYJ.Common.HttpHelper.DoGet(url);
Post model = new Post();
model.PostID = gather.GetNewID();
model.AuthorID = this.txtPostUserID.Text;
if (this.comboBox_category.SelectedValue != null)
{
model.CateID = this.comboBox_category.SelectedValue.ToString();
}
model.AuthorUserName = this.txtPostUserName.Text.Trim();
model.Title = ana.Title;
model.Content = ana.Content;
//暂时全部允许下载
model.AttachmentLimit = 0;
model.FromAuthor = ana.Author;
if (!String.IsNullOrEmpty(model.FromAuthor) && this.txtFromAuthor.Text.Trim() != "")
{
model.FromAuthor = this.txtFromAuthor.Text.Trim();
}
model.FromSourceUrl = url;
model.FromSource = ana.FromSource;
if (!String.IsNullOrEmpty(model.FromSource) && this.txtFromSource.Text.Trim() != "")
{
model.FromSource = this.txtFromSource.Text.Trim();
}
model.AttachmentCollection = null;
model.PostBy = "MultiGather";
if (String.IsNullOrEmpty(model.Content))
{
this.logList1.AddErrorItem("线程" + threadid + ":没有分析到" + url + "内容");
Step();
return;
}
List<Attachment> attachmentCollection = new List<Attachment>();
#region 获取html中的图片
if (this.checkBox_DownPic.IsChecked == true)
{
List<string> imageList = HttpAnalyze.GetTagAttribute(model.Content, "img", "src");//图片列表
for (int i = 0; i < imageList.Count; i++)
{
string imageRealPath = HttpAnalyze.GetRealPath(imageList[i], url);
string fileName = System.IO.Path.GetFileName(imageRealPath.IndexOf("?") == -1 ? imageRealPath : imageRealPath.Substring(0, imageRealPath.IndexOf("?")));
this.logList1.AddItem("线程" + threadid + ":分析到远程图片:" + imageRealPath);
Attachment att = new Attachment();
att.fileName = fileName;
att.fileUrl = imageRealPath;
att.isImage = true;
attachmentCollection.Add(att);
}
}
#endregion
#region 获取html中的附件
if (this.chk_DownAttachment.IsChecked == true)
{
IEnumerable<Attachment> atts = ana.AttachmentCollection;
if (atts != null && atts.Count() > 0)
{
string baseUrl = Regex.Match(url, "http://(.*?)/").Value;
for (int i = 0; i < atts.Count(); i++)
{
string extension = System.IO.Path.GetExtension(atts.ElementAt(i).fileName).ToLower();
bool isImage = (extension == ".jpg" || extension == ".png" || extension == ".bmp" || extension == ".gif");
Attachment att = new Attachment();
att.fileName = atts.ElementAt(i).fileName;
att.fileUrl = baseUrl + atts.ElementAt(i).fileUrl;
att.isImage = isImage;
att.objectTag = "attachment";
attachmentCollection.Add(att);
}
}
}
#endregion
#region 上传附件和图片
FYJ.Upload.Util.FileSave save = new FYJ.Upload.Util.FileSave();
if (attachmentCollection.Count > 0)
{
this.attachmentProgress.Visibility = Visibility.Visible;
this.attachmentProgress.Maximum = attachmentCollection.Count;
for (int i = 0; i < attachmentCollection.Count; i++)
{
Attachment att = attachmentCollection[i];
Stream stream = null;
UploadResult queryFromResult = null;
if (att.fileUrl.StartsWith("http"))
{
queryFromResult = save.QueryFileByFromUrl(att.fileUrl).FirstOrDefault();
//如果已从该来源Url上下载过该文件
if (queryFromResult == null)
{
this.txtState.Text = "线程" + threadid + ":正在下载" + att.fileUrl;
HttpWebResponse res = FYJ.Common.HttpHelper.GetResponse(att.fileUrl, "GET");
stream = res.GetResponseStream();
}
}
else
{
stream = new FileStream(att.fileUrl, FileMode.Open);
}
this.txtState.Text = "线程" + threadid + ":正在上传文件...";
save.ObjectID = model.PostID;
save.ObjectTag = att.objectTag;
if (gather is DisThread)
{
save.FileTag = "discuz";
save.ObjectType = "forum";
save.UploadDir = "forum";
}
if (gather is DisArticle)
{
save.FileTag = "discuz";
save.ObjectType = "portal";
save.UploadDir = "portal";
}
if (gather is BlogArticle)
{
save.FileTag = "blog";
save.ObjectType = "blog";
save.UploadDir = "blog";
}
if (gather is WordArticle)
{
save.FileTag = "wordpress";
save.ObjectType = "wordpress";
save.UploadDir = "wordpress";
}
FYJ.Upload.UploadResult upresult;
if (stream != null)
{
upresult = save.Save(stream, System.IO.Path.GetFileName(att.fileUrl), att.fileUrl);
}
else
{
upresult = queryFromResult;
//保存文件关系
save.SaveFileRelationDb(upresult.ID, model.PostID, null, att.objectTag);
}
att.fileID = upresult.ID;
att.fileName = upresult.FileName;
att.fileSize = upresult.Size;
this.logList1.AddItem("线程" + threadid + ":成功下载文件并上传到服务器:" + att.fileUrl);
//替换img标签的文件
model.Content = model.Content.Replace(att.fileUrl, upresult.Url);
//必须在上句的下面
att.fileUrl = upresult.Url;
this.attachmentProgress.Value = (i + 1);
}
}
#endregion
Thread.Sleep(3000);
this.logList1.AddItem("线程" + threadid + ":采集测试完成..." + model.Title);
//MessageEx message = gather.Insert(model);
//if (message.Code > 0)
//{
// this.logList1.AddItem("线程" + threadid + " " + message.Message);
//}
//else
//{
// this.logList1.AddErrorItem("线程" + threadid + "从 " + url + " " + message.Message);
//}
}
catch (Exception ex)
{
this.logList1.AddErrorItem("线程" + threadid + ":采集 " + url + " 发生异常:" + ex.Message);
}
Step();
}
/// <summary>
/// 进度条加1
/// </summary>
private void Step()
{
Monitor.Enter(this.progressState);
this.progressState.Value = this.progressState.Value + 1;
Monitor.Exit(this.progressState);
}
private void progressState_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
this.Dispatcher.Invoke((Action)(() =>
{
if (this.progressState.Value == this.progressState.Maximum)
{
this.txtState.Text = "发布完成";
this.progressState.Value = this.progressState.Maximum;
}
else
{
this.txtState.Text = "正在发布..." + this.progressState.Value + "/" + this.progressState.Maximum;
}
this.taskbarItemInfo1.ProgressState = TaskbarItemProgressState.Normal;
this.taskbarItemInfo1.ProgressValue = e.NewValue / this.progressState.Maximum;
if (e.NewValue == this.progressState.Maximum)
{
this.taskbarItemInfo1.ProgressState = TaskbarItemProgressState.None;
}
}));
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
cancelTokenSource.Cancel();
this.btnStart.IsEnabled = true;
}
}
}
珂珂的个人博客 - 一个程序猿的个人网站
5/16/2015 5:43:20 PM 118.193.198....
沙发