Skip to content

Commit

Permalink
Merge pull request #9 from emoacht/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
emoacht committed Jun 14, 2015
2 parents 40b0664 + 8c3e1f7 commit 552d96b
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 77 deletions.
148 changes: 75 additions & 73 deletions DiskGazer/Models/Operation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ private set
#endregion


private ConcurrentQueue<RawData> _rawDataQueue; // Queue of raw data

private readonly List<Dictionary<double, double>> _diskScoresRun = new List<Dictionary<double, double>>(); // Temporary scores of runs
private KeyValuePair<double, double>[] _diskScoresStep; // Temporary scores of steps
private int _diskScoresStepCount; // The number of temporary scores of steps
Expand All @@ -82,20 +80,21 @@ internal async Task ReadAnalyzeAsync(IProgress<ProgressInfo> progress)
IsCanceled = false;
_currentSpeed = 0D;

_rawDataQueue = new ConcurrentQueue<RawData>();

_diskScoresRun.Clear();

try
{
_tokenSource = new CancellationTokenSource();
_isTokenSourceDisposed = false;

// Read and analyze disk in parallel.
var readTask = ReadAsnyc(progress, _tokenSource.Token);
var analyzeTask = AnalyzeAsync(progress, _tokenSource.Token);
using (var rawDataCollection = new BlockingCollection<RawData>())
{
// Read and analyze disk in parallel.
var readTask = ReadAsnyc(rawDataCollection, progress, _tokenSource.Token);
var analyzeTask = AnalyzeAsync(rawDataCollection, progress, _tokenSource.Token);

await Task.WhenAll(readTask, analyzeTask);
await Task.WhenAll(readTask, analyzeTask);
}
}
catch (OperationCanceledException)
{
Expand Down Expand Up @@ -137,13 +136,13 @@ internal void StopReadAnalyze(IProgress<ProgressInfo> progress)

#region Read (Private)

private async Task ReadAsnyc(IProgress<ProgressInfo> progress, CancellationToken cancellationToken)
private async Task ReadAsnyc(BlockingCollection<RawData> rawDataCollection, IProgress<ProgressInfo> progress, CancellationToken cancellationToken)
{
try
{
IsReading = true;

await ReadBaseAsync(progress, cancellationToken);
await ReadBaseAsync(rawDataCollection, progress, cancellationToken);

progress.Report(new ProgressInfo("Analyzing"));
}
Expand All @@ -162,57 +161,63 @@ private async Task ReadAsnyc(IProgress<ProgressInfo> progress, CancellationToken
}
}

private async Task ReadBaseAsync(IProgress<ProgressInfo> progress, CancellationToken cancellationToken)
private async Task ReadBaseAsync(BlockingCollection<RawData> rawDataCollection, IProgress<ProgressInfo> progress, CancellationToken cancellationToken)
{
for (int i = 1; i <= Settings.Current.NumRun; i++)
try
{
for (int j = 0; j < NumStep; j++)
for (int i = 1; i <= Settings.Current.NumRun; i++)
{
cancellationToken.ThrowIfCancellationRequested();
for (int j = 0; j < NumStep; j++)
{
cancellationToken.ThrowIfCancellationRequested();

var rawData = new RawData();
rawData.Run = i;
rawData.Step = j + 1;
rawData.Result = ReadResult.NotYet;
var rawData = new RawData();
rawData.Run = i;
rawData.Step = j + 1;
rawData.Result = ReadResult.NotYet;

// Update progress before reading.
progress.Report(ComposeProgressInfo(rawData));
// Update progress before reading.
progress.Report(ComposeProgressInfo(rawData));

rawData.BlockOffsetMultiple = j;
rawData.BlockOffsetMultiple = j;

switch (Settings.Current.Method)
{
case ReadMethod.Native:
rawData = await DiskReader.ReadDiskNativeAsync(rawData, cancellationToken);
break;
switch (Settings.Current.Method)
{
case ReadMethod.Native:
rawData = await DiskReader.ReadDiskNativeAsync(rawData, cancellationToken);
break;

case ReadMethod.P_Invoke:
rawData = await DiskReader.ReadDiskPInvokeAsync(rawData, cancellationToken);
break;
}
case ReadMethod.P_Invoke:
rawData = await DiskReader.ReadDiskPInvokeAsync(rawData, cancellationToken);
break;
}

cancellationToken.ThrowIfCancellationRequested();
cancellationToken.ThrowIfCancellationRequested();

// Update progress after reading.
progress.Report(ComposeProgressInfo(rawData));
// Update progress after reading.
progress.Report(ComposeProgressInfo(rawData));

if (rawData.Result == ReadResult.Success) // If success.
{
// Store raw data into queue.
_rawDataQueue.Enqueue(rawData);
if (rawData.Result == ReadResult.Success) // If success.
{
rawDataCollection.Add(rawData, cancellationToken);

// Leave current speed.
if (rawData.Data != null)
// Leave current speed.
if (rawData.Data != null)
{
_currentSpeed = rawData.Data.Average();
}
}
else if (rawData.Result == ReadResult.Failure) // If failure.
{
_currentSpeed = rawData.Data.Average();
throw new Exception(rawData.Message);
}
}
else if (rawData.Result == ReadResult.Failure) // If failure.
{
throw new Exception(rawData.Message);
}
}
}
finally
{
rawDataCollection.CompleteAdding();
}
}

private ProgressInfo ComposeProgressInfo(RawData rawData)
Expand Down Expand Up @@ -276,46 +281,43 @@ private ProgressInfo ComposeProgressInfo(RawData rawData)

#region Analyze (Private)

private readonly TimeSpan _waitTime = TimeSpan.FromMilliseconds(100); // Wait time when queue has no data

private async Task AnalyzeAsync(IProgress<ProgressInfo> progress, CancellationToken cancellationToken)
private async Task AnalyzeAsync(BlockingCollection<RawData> rawDataCollection, IProgress<ProgressInfo> progress, CancellationToken cancellationToken)
{
try
{
IsAnalyzing = true;

while (IsReading || !_rawDataQueue.IsEmpty)
await Task.Factory.StartNew(() =>
{
cancellationToken.ThrowIfCancellationRequested();

if (_rawDataQueue.IsEmpty)
try
{
// Wait for new data.
await Task.Delay(_waitTime, cancellationToken);
continue;
}

// Dequeue raw data from queue.
RawData rawData;
if (!_rawDataQueue.TryDequeue(out rawData))
throw new Exception("Failed to dequeue raw data from queue.");

// Update progress before analyzing.
var innerStatusIn = String.Format("[{0}/{1} - {2}/{3} Analyzer In]",
rawData.Run, Settings.Current.NumRun,
rawData.Step, NumStep);
// BlockingCollection.Take and BlockingCollection.GetConsumingEnumerable methods
// seem to block the entire application permanently if running on main thread.
foreach (var rawData in rawDataCollection.GetConsumingEnumerable(cancellationToken))
{
// Update progress before analyzing.
var innerStatusIn = String.Format("[{0}/{1} - {2}/{3} Analyzer In]",
rawData.Run, Settings.Current.NumRun,
rawData.Step, NumStep);
progress.Report(new ProgressInfo(innerStatusIn, false));
progress.Report(new ProgressInfo(innerStatusIn, false));
await Task.Run(() => AnalyzeBase(rawData, progress, cancellationToken), cancellationToken);
AnalyzeBase(rawData, progress, cancellationToken);
// Update progress after analyzing.
var innerStatusOut = String.Format("[{0}/{1} - {2}/{3} Analyzer Out ({4})]",
_diskScoresRun.Count, Settings.Current.NumRun,
_diskScoresStepCount, NumStep, _diskScoresStep.Count());
// Update progress after analyzing.
var innerStatusOut = String.Format("[{0}/{1} - {2}/{3} Analyzer Out ({4})]",
_diskScoresRun.Count, Settings.Current.NumRun,
_diskScoresStepCount, NumStep, _diskScoresStep.Count());
progress.Report(new ProgressInfo(innerStatusOut, false));
}
progress.Report(new ProgressInfo(innerStatusOut, false));
}
}
catch (OperationCanceledException)
{
// A OperationCanceledException from BlockingCollection.GetConsumingEnumerable method
// cannot be caught outside of this task.
}
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
catch (OperationCanceledException)
{
Expand Down
4 changes: 2 additions & 2 deletions DiskGazer/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@
// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を
// 既定値にすることができます:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.1.0")]
[assembly: AssemblyFileVersion("1.0.1.0")]
2 changes: 1 addition & 1 deletion DiskGazer/Views/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
xmlns:controls="clr-namespace:DiskGazer.Views.Controls"
xmlns:converters="clr-namespace:DiskGazer.Views.Converters"
x:Name="MainWindowRoot"
Title="{Binding Source={x:Static views:ProductInfo.NameVersionShort}, Mode=OneWay}"
Title="{Binding Source={x:Static views:ProductInfo.NameVersionMiddle}, Mode=OneWay}"
FontFamily="Verdana" FontSize="11"
Width="600" Height="460"
Icon="/DiskGazer;component/Resources/Gazer.ico"
Expand Down
2 changes: 1 addition & 1 deletion DiskGazer/Views/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,7 @@ private static float GetPerc(double targetLength, int baseLength)
{
var sampleNum = targetLength / (double)baseLength;

return (float)sampleNum * 100F;
return Math.Min((float)sampleNum * 100F, 100F);
}

private static Size TextSize(int num, System.Drawing.Font font)
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ The logic for sequential read test is based on that of [CrystalDiskMark][1] (3.0

##History

Ver 1.0.1 2015-6-14

- Fixed possible exception

Ver 1.0.0 2015-3-31

- First decent release
Expand Down

0 comments on commit 552d96b

Please sign in to comment.