mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-23 20:47:25 -08:00
fix<Avatar>: fix crash when more than one thread wants to access same avatar file
This commit is contained in:
parent
6f08d03d04
commit
c22ea8f4cf
3 changed files with 49 additions and 46 deletions
|
@ -103,6 +103,9 @@ namespace SourceGit {
|
|||
Setting = JsonSerializer.Deserialize<Preference>(File.ReadAllText(settingFile));
|
||||
}
|
||||
|
||||
// Make sure avatar cache folder exists
|
||||
if (!Directory.Exists(Helpers.Avatar.CACHE_PATH)) Directory.CreateDirectory(Helpers.Avatar.CACHE_PATH);
|
||||
|
||||
// Try auto configure git via registry.
|
||||
if (Setting == null || !IsGitConfigured) {
|
||||
var root = RegistryKey.OpenBaseKey(
|
||||
|
|
|
@ -2,8 +2,10 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
|
@ -36,6 +38,14 @@ namespace SourceGit.Helpers {
|
|||
Brushes.DarkViolet
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Path to cache downloaded avatars
|
||||
/// </summary>
|
||||
public static readonly string CACHE_PATH = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||
"SourceGit",
|
||||
"avatars");
|
||||
|
||||
/// <summary>
|
||||
/// User property definition.
|
||||
/// </summary>
|
||||
|
@ -53,26 +63,15 @@ namespace SourceGit.Helpers {
|
|||
set { SetValue(UserProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loading request
|
||||
/// </summary>
|
||||
private class Request {
|
||||
public BitmapImage img = null;
|
||||
public List<Avatar> targets = new List<Avatar>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Path to cache downloaded avatars
|
||||
/// </summary>
|
||||
private static readonly string CACHE_PATH = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||
"SourceGit",
|
||||
"avatars");
|
||||
|
||||
/// <summary>
|
||||
/// Current requests.
|
||||
/// </summary>
|
||||
private static Dictionary<string, Request> requesting = new Dictionary<string, Request>();
|
||||
private static Dictionary<string, List<Avatar>> requesting = new Dictionary<string, List<Avatar>>();
|
||||
|
||||
/// <summary>
|
||||
/// Loaded images.
|
||||
/// </summary>
|
||||
private static Dictionary<string, BitmapImage> loaded = new Dictionary<string, BitmapImage>();
|
||||
|
||||
/// <summary>
|
||||
/// Render implementation.
|
||||
|
@ -112,10 +111,10 @@ namespace SourceGit.Helpers {
|
|||
/// </summary>
|
||||
private void ReloadImage(Git.User oldUser) {
|
||||
if (oldUser != null && requesting.ContainsKey(oldUser.Email)) {
|
||||
if (requesting[oldUser.Email].targets.Count <= 1) {
|
||||
if (requesting[oldUser.Email].Count <= 1) {
|
||||
requesting.Remove(oldUser.Email);
|
||||
} else {
|
||||
requesting[oldUser.Email].targets.Remove(this);
|
||||
requesting[oldUser.Email].Remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,8 +124,13 @@ namespace SourceGit.Helpers {
|
|||
if (User == null) return;
|
||||
|
||||
var email = User.Email;
|
||||
if (loaded.ContainsKey(email)) {
|
||||
Source = loaded[email];
|
||||
return;
|
||||
}
|
||||
|
||||
if (requesting.ContainsKey(email)) {
|
||||
requesting[email].targets.Add(this);
|
||||
requesting[email].Add(this);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -137,36 +141,32 @@ namespace SourceGit.Helpers {
|
|||
|
||||
string filePath = Path.Combine(CACHE_PATH, md5);
|
||||
if (File.Exists(filePath)) {
|
||||
Source = new BitmapImage(new Uri(filePath));
|
||||
var img = new BitmapImage(new Uri(filePath));
|
||||
loaded.Add(email, img);
|
||||
Source = img;
|
||||
return;
|
||||
}
|
||||
|
||||
requesting.Add(email, new Request());
|
||||
requesting[email].targets.Add(this);
|
||||
requesting.Add(email, new List<Avatar>());
|
||||
requesting[email].Add(this);
|
||||
|
||||
BitmapImage downloading = new BitmapImage(new Uri("https://www.gravatar.com/avatar/" + md5 + "?d=404"));
|
||||
requesting[email].img = downloading;
|
||||
downloading.DownloadCompleted += (o, e) => {
|
||||
var owner = o as BitmapImage;
|
||||
if (owner != null) {
|
||||
if (!Directory.Exists(CACHE_PATH)) Directory.CreateDirectory(CACHE_PATH);
|
||||
|
||||
var encoder = new PngBitmapEncoder();
|
||||
encoder.Frames.Add(BitmapFrame.Create(owner));
|
||||
using (var fs = new FileStream(filePath, FileMode.Create)) {
|
||||
encoder.Save(fs);
|
||||
}
|
||||
Task.Run(() => {
|
||||
try {
|
||||
var agent = new WebClient();
|
||||
var data = agent.DownloadData("https://www.gravatar.com/avatar/" + md5 + "?d=404");
|
||||
//var data = agent.DownloadData("https://cdn.s.loli.top/avatar/" + md5 + "?d=404");
|
||||
File.WriteAllBytes(filePath, data);
|
||||
|
||||
if (requesting.ContainsKey(email)) {
|
||||
BitmapImage exists = new BitmapImage(new Uri(filePath));
|
||||
foreach (var one in requesting[email].targets) one.Source = exists;
|
||||
requesting.Remove(email);
|
||||
Dispatcher.Invoke(() => {
|
||||
var img = new BitmapImage(new Uri(filePath));
|
||||
loaded[email] = img;
|
||||
foreach (var one in requesting[email]) one.Source = img;
|
||||
requesting.Remove(email);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
downloading.DownloadFailed += (o, e) => {
|
||||
requesting.Remove(email);
|
||||
};
|
||||
} catch {}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
</Style>
|
||||
</DataGrid.Resources>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTemplateColumn Width="*" IsReadOnly="True">
|
||||
<DataGridTemplateColumn x:Name="commitGraphColumn" Width="*" IsReadOnly="True">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal" Margin="{Binding GraphOffset, Converter={StaticResource CommitTitleMargin}}">
|
||||
|
@ -144,7 +144,7 @@
|
|||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
<DataGridTextColumn Width="84" IsReadOnly="True" Binding="{Binding Committer.Name}" ElementStyle="{StaticResource Style.DataGridText.NoPadding}"/>
|
||||
<DataGridTextColumn Width="Auto" IsReadOnly="True" Binding="{Binding Committer.Name}" ElementStyle="{StaticResource Style.DataGridText.NoPadding}"/>
|
||||
<DataGridTextColumn Width="84" IsReadOnly="True" Binding="{Binding ShortSHA}" ElementStyle="{StaticResource Style.DataGridText}"/>
|
||||
<DataGridTextColumn Width="128" IsReadOnly="True" Binding="{Binding Committer.Time}" ElementStyle="{StaticResource Style.DataGridText.NoPadding}"/>
|
||||
</DataGrid.Columns>
|
||||
|
@ -162,7 +162,7 @@
|
|||
</DataGrid>
|
||||
|
||||
<!-- Commit Graph -->
|
||||
<Border x:Name="commitGraphContainer" Grid.Row="1" Margin="0,0,342,0" ClipToBounds="True" IsHitTestVisible="False">
|
||||
<Border x:Name="commitGraphContainer" Grid.Row="1" Width="{Binding ElementName=commitGraphColumn, Path=ActualWidth}" ClipToBounds="True" IsHitTestVisible="False" HorizontalAlignment="Left">
|
||||
<helpers:CommitGraph
|
||||
x:Name="commitGraph"
|
||||
Width="{Binding ElementName=commitGraphContainer, Path=ActualWidth}"
|
||||
|
|
Loading…
Reference in a new issue