2016-08-02 06:13:58 +02:00
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion= "14.0" DefaultTargets= "Build" xmlns= "http://schemas.microsoft.com/developer/msbuild/2003" >
<Import Project= "$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition= "Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup >
<Configuration Condition= " '$(Configuration)' == '' " > Debug</Configuration>
<Platform Condition= " '$(Platform)' == '' " > AnyCPU</Platform>
<ProjectGuid > {13949B41-787C-4558-90AE-A9F9E7F86B1F}</ProjectGuid>
<OutputType > WinExe</OutputType>
<AppDesignerFolder > Properties</AppDesignerFolder>
2017-01-13 23:47:12 +01:00
<RootNamespace > ArchiSteamFarm</RootNamespace>
2016-08-02 06:13:58 +02:00
<AssemblyName > GUI</AssemblyName>
<TargetFrameworkVersion > v4.6.1</TargetFrameworkVersion>
<FileAlignment > 512</FileAlignment>
<AutoGenerateBindingRedirects > true</AutoGenerateBindingRedirects>
2016-08-03 17:16:11 +02:00
<NuGetPackageImportStamp >
</NuGetPackageImportStamp>
2016-08-02 06:13:58 +02:00
</PropertyGroup>
<PropertyGroup Condition= " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' " >
<PlatformTarget > AnyCPU</PlatformTarget>
<DebugSymbols > true</DebugSymbols>
<DebugType > full</DebugType>
<Optimize > false</Optimize>
<OutputPath > bin\Debug\</OutputPath>
<DefineConstants > DEBUG;TRACE</DefineConstants>
<ErrorReport > prompt</ErrorReport>
<WarningLevel > 4</WarningLevel>
2016-08-27 08:40:40 +02:00
<Prefer32Bit > false</Prefer32Bit>
2016-08-02 06:13:58 +02:00
</PropertyGroup>
<PropertyGroup Condition= " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " >
<PlatformTarget > AnyCPU</PlatformTarget>
2016-08-27 08:40:40 +02:00
<DebugType > none</DebugType>
2016-08-02 06:13:58 +02:00
<Optimize > true</Optimize>
<OutputPath > bin\Release\</OutputPath>
2016-08-27 08:40:40 +02:00
<DefineConstants >
</DefineConstants>
2016-08-02 06:13:58 +02:00
<ErrorReport > prompt</ErrorReport>
<WarningLevel > 4</WarningLevel>
2016-08-27 08:40:40 +02:00
<Prefer32Bit > false</Prefer32Bit>
2016-08-02 06:13:58 +02:00
</PropertyGroup>
<PropertyGroup >
2016-11-11 02:00:27 +01:00
<ApplicationIcon > ..\ArchiSteamFarm\ASF.ico</ApplicationIcon>
2016-08-02 06:13:58 +02:00
</PropertyGroup>
2016-08-27 09:34:08 +02:00
<PropertyGroup >
<RunPostBuildEvent > OnOutputUpdated</RunPostBuildEvent>
</PropertyGroup>
2016-08-02 06:13:58 +02:00
<ItemGroup >
2017-05-17 02:36:49 +02:00
<Reference Include= "HtmlAgilityPack, Version=1.5.0.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL" >
<HintPath > ..\packages\HtmlAgilityPack.1.5.0-beta2\lib\Net45\HtmlAgilityPack.dll</HintPath>
2016-08-02 06:13:58 +02:00
</Reference>
2017-05-06 02:17:40 +02:00
<Reference Include= "Humanizer, Version=2.2.0.0, Culture=neutral, PublicKeyToken=979442b78dfc278e, processorArchitecture=MSIL" >
<HintPath > ..\packages\Humanizer.Core.2.2.0\lib\netstandard1.0\Humanizer.dll</HintPath>
2017-04-08 05:05:09 +02:00
</Reference>
2017-03-01 22:46:02 +01:00
<Reference Include= "Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL" >
2017-04-05 14:18:44 +02:00
<HintPath > ..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
2016-08-02 06:13:58 +02:00
</Reference>
Fix async/await with ConcurrentHashSet
Now this is a nice bug that was found accidentally by ArchiBoT...
ReaderWriterLockSlim() is very decent solution, but it's thread-based, and we're using our ConcurrentHashSet in mixed async/sync context. This means that if we use something like:
foreach (var item in concHashSet) {
await AnythingAsync().ConfigureAwait(false);
}
It's totally possible that we'll request read lock as thread 1, and release the read lock as thread 2, which will lead to RWLock exception => System.Threading.SynchronizationLockException: The read lock is being released without being held.
Fortunately it looks like we didn't have any scenario like this in ASF, as this was possible only when we async/await while enumerating over ConcurrentHashSet, so that specific bug didn't affect ASF codebase (yet). Still, I must fix this as current implementation is not thread-safe, so our HashSet is in fact not concurrent in the first place.
I analyzed possible solutions and there are basically 3: either using ConcurrentDictionary and wrapping around it, replacing lock with SemaphoreSlim, or using third-party AsyncReaderWriterLock from StephenCleary. SemaphoreSlim entirely kills the concept of multiple readers one writer, and could affect performance negatively, moreover - it doesn't support upgreadable lock scenario we have with ReplaceIfNeededWith(). Concurrent dictionary would be nice if I didn't have that awful memory hit from storing mandatory pointless value, plus I don't really like concept of wrapping around conc dictionary if I can simply use it right away and drop my conc hashset entirely. AsyncReaderWriterLock seem to be really well written, and works on Mono + should be compatible with .NET core in the future, so we should go for it as it's the best bet both performance-wise and memory-wise.
This brings another package dependency and changes a bit backend of ConcurrentHashSet
2017-02-07 20:14:51 +01:00
<Reference Include= "Nito.AsyncEx, Version=4.0.1.0, Culture=neutral, processorArchitecture=MSIL" >
<HintPath > ..\packages\Nito.AsyncEx.4.0.1\lib\net45\Nito.AsyncEx.dll</HintPath>
<Private > True</Private>
</Reference>
<Reference Include= "Nito.AsyncEx.Concurrent, Version=4.0.1.0, Culture=neutral, processorArchitecture=MSIL" >
<HintPath > ..\packages\Nito.AsyncEx.4.0.1\lib\net45\Nito.AsyncEx.Concurrent.dll</HintPath>
<Private > True</Private>
</Reference>
<Reference Include= "Nito.AsyncEx.Enlightenment, Version=4.0.1.0, Culture=neutral, processorArchitecture=MSIL" >
<HintPath > ..\packages\Nito.AsyncEx.4.0.1\lib\net45\Nito.AsyncEx.Enlightenment.dll</HintPath>
<Private > True</Private>
</Reference>
2016-11-05 08:03:42 +01:00
<Reference Include= "NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL" >
2017-04-29 23:26:59 +02:00
<HintPath > ..\packages\NLog.5.0.0-beta07\lib\net45\NLog.dll</HintPath>
2016-08-02 06:13:58 +02:00
</Reference>
2016-08-02 08:50:31 +02:00
<Reference Include= "NLog.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL" >
<HintPath > ..\packages\NLog.Windows.Forms.4.2.3\lib\net35\NLog.Windows.Forms.dll</HintPath>
<Private > True</Private>
</Reference>
2017-03-30 20:44:03 +02:00
<Reference Include= "protobuf-net, Version=2.1.0.0, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL" >
<HintPath > ..\packages\protobuf-net.2.1.0\lib\net451\protobuf-net.dll</HintPath>
2016-08-02 06:13:58 +02:00
</Reference>
2017-03-30 20:44:03 +02:00
<Reference Include= "SteamKit2, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL" >
2017-04-24 06:27:50 +02:00
<HintPath > ..\packages\SteamKit2.2.0.0-Alpha4\lib\net46\SteamKit2.dll</HintPath>
2016-08-02 06:13:58 +02:00
</Reference>
<Reference Include= "System" />
2017-04-29 23:26:59 +02:00
<Reference Include= "System.Configuration" />
2016-08-02 06:13:58 +02:00
<Reference Include= "System.Core" />
2017-04-29 23:26:59 +02:00
<Reference Include= "System.Data" />
2016-08-02 06:13:58 +02:00
<Reference Include= "System.IO.Compression" />
Fix async/await with ConcurrentHashSet
Now this is a nice bug that was found accidentally by ArchiBoT...
ReaderWriterLockSlim() is very decent solution, but it's thread-based, and we're using our ConcurrentHashSet in mixed async/sync context. This means that if we use something like:
foreach (var item in concHashSet) {
await AnythingAsync().ConfigureAwait(false);
}
It's totally possible that we'll request read lock as thread 1, and release the read lock as thread 2, which will lead to RWLock exception => System.Threading.SynchronizationLockException: The read lock is being released without being held.
Fortunately it looks like we didn't have any scenario like this in ASF, as this was possible only when we async/await while enumerating over ConcurrentHashSet, so that specific bug didn't affect ASF codebase (yet). Still, I must fix this as current implementation is not thread-safe, so our HashSet is in fact not concurrent in the first place.
I analyzed possible solutions and there are basically 3: either using ConcurrentDictionary and wrapping around it, replacing lock with SemaphoreSlim, or using third-party AsyncReaderWriterLock from StephenCleary. SemaphoreSlim entirely kills the concept of multiple readers one writer, and could affect performance negatively, moreover - it doesn't support upgreadable lock scenario we have with ReplaceIfNeededWith(). Concurrent dictionary would be nice if I didn't have that awful memory hit from storing mandatory pointless value, plus I don't really like concept of wrapping around conc dictionary if I can simply use it right away and drop my conc hashset entirely. AsyncReaderWriterLock seem to be really well written, and works on Mono + should be compatible with .NET core in the future, so we should go for it as it's the best bet both performance-wise and memory-wise.
This brings another package dependency and changes a bit backend of ConcurrentHashSet
2017-02-07 20:14:51 +01:00
<Reference Include= "System.Net" />
2017-04-29 23:26:59 +02:00
<Reference Include= "System.Runtime.Serialization" />
2016-08-02 06:13:58 +02:00
<Reference Include= "System.Security" />
<Reference Include= "Microsoft.CSharp" />
<Reference Include= "System.Drawing" />
2017-03-29 13:01:36 +02:00
<Reference Include= "System.Net.Http" />
2017-04-29 23:26:59 +02:00
<Reference Include= "System.ServiceModel" />
<Reference Include= "System.Transactions" />
2016-08-02 06:13:58 +02:00
<Reference Include= "System.Windows.Forms" />
<Reference Include= "System.Xml" />
</ItemGroup>
<ItemGroup >
<Compile Include= "..\ArchiSteamFarm\ArchiHandler.cs" >
<Link > ArchiHandler.cs</Link>
</Compile>
2016-11-06 12:06:02 +01:00
<Compile Include= "..\ArchiSteamFarm\ArchiLogger.cs" >
<Link > ArchiLogger.cs</Link>
</Compile>
2016-08-02 06:13:58 +02:00
<Compile Include= "..\ArchiSteamFarm\ArchiWebHandler.cs" >
<Link > ArchiWebHandler.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\ASF.cs" >
<Link > ASF.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\Bot.cs" >
<Link > Bot.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\BotConfig.cs" >
<Link > BotConfig.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\BotDatabase.cs" >
<Link > BotDatabase.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\CardsFarmer.cs" >
<Link > CardsFarmer.cs</Link>
</Compile>
2016-12-11 04:23:44 +01:00
<Compile Include= "..\ArchiSteamFarm\CMsgs\CMsgClientClanInviteAction.cs" >
<Link > CMsgs\CMsgClientClanInviteAction.cs</Link>
</Compile>
2016-08-02 06:13:58 +02:00
<Compile Include= "..\ArchiSteamFarm\ConcurrentEnumerator.cs" >
<Link > ConcurrentEnumerator.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\ConcurrentHashSet.cs" >
<Link > ConcurrentHashSet.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\CryptoHelper.cs" >
<Link > CryptoHelper.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\Debugging.cs" >
<Link > Debugging.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\GlobalConfig.cs" >
<Link > GlobalConfig.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\GlobalDatabase.cs" >
<Link > GlobalDatabase.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\InMemoryServerListProvider.cs" >
<Link > InMemoryServerListProvider.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\IPAddressConverter.cs" >
<Link > IPAddressConverter.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\IPEndPointConverter.cs" >
<Link > IPEndPointConverter.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\JSON\GitHub.cs" >
<Link > JSON\GitHub.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\JSON\Steam.cs" >
<Link > JSON\Steam.cs</Link>
</Compile>
2017-01-06 12:11:11 +01:00
<Compile Include= "..\ArchiSteamFarm\Localization\Strings.Designer.cs" >
<Link > Localization\Strings.Designer.cs</Link>
2017-01-13 23:47:12 +01:00
<AutoGen > True</AutoGen>
<DesignTime > True</DesignTime>
<DependentUpon > Strings.resx</DependentUpon>
2017-01-06 12:11:11 +01:00
</Compile>
2016-08-02 06:13:58 +02:00
<Compile Include= "..\ArchiSteamFarm\MobileAuthenticator.cs" >
<Link > MobileAuthenticator.cs</Link>
</Compile>
2017-02-05 13:52:00 +01:00
<Compile Include= "..\ArchiSteamFarm\OS.cs" >
<Link > OS.cs</Link>
</Compile>
2016-08-02 06:13:58 +02:00
<Compile Include= "..\ArchiSteamFarm\Runtime.cs" >
<Link > Runtime.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\SharedInfo.cs" >
<Link > SharedInfo.cs</Link>
</Compile>
2016-12-04 01:07:37 +01:00
<Compile Include= "..\ArchiSteamFarm\Statistics.cs" >
<Link > Statistics.cs</Link>
</Compile>
2016-12-23 03:01:37 +01:00
<Compile Include= "..\ArchiSteamFarm\SteamSaleEvent.cs" >
<Link > SteamSaleEvent.cs</Link>
</Compile>
2017-01-31 01:10:01 +01:00
<Compile Include= "..\ArchiSteamFarm\SteamTarget.cs" >
<Link > SteamTarget.cs</Link>
</Compile>
2016-08-02 06:13:58 +02:00
<Compile Include= "..\ArchiSteamFarm\Trading.cs" >
<Link > Trading.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\Utilities.cs" >
<Link > Utilities.cs</Link>
</Compile>
<Compile Include= "..\ArchiSteamFarm\WebBrowser.cs" >
<Link > WebBrowser.cs</Link>
</Compile>
2016-08-02 12:13:15 +02:00
<Compile Include= "BotStatusForm.cs" >
<SubType > Form</SubType>
</Compile>
<Compile Include= "BotStatusForm.Designer.cs" >
<DependentUpon > BotStatusForm.cs</DependentUpon>
</Compile>
<Compile Include= "Events.cs" />
2016-08-02 08:50:31 +02:00
<Compile Include= "MainForm.cs" >
2016-08-02 06:13:58 +02:00
<SubType > Form</SubType>
</Compile>
2016-08-02 08:50:31 +02:00
<Compile Include= "MainForm.Designer.cs" >
<DependentUpon > MainForm.cs</DependentUpon>
2016-08-02 06:13:58 +02:00
</Compile>
2016-08-02 08:50:31 +02:00
<Compile Include= "Logging.cs" />
2016-08-02 06:13:58 +02:00
<Compile Include= "Program.cs" />
<Compile Include= "Properties\AssemblyInfo.cs" />
2017-01-13 23:47:12 +01:00
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.af-ZA.resx" >
<Link > Localization\Strings.af-ZA.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.ar-SA.resx" >
<Link > Localization\Strings.ar-SA.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.bg-BG.resx" >
<Link > Localization\Strings.bg-BG.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.ca-ES.resx" >
<Link > Localization\Strings.ca-ES.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.cs-CZ.resx" >
<Link > Localization\Strings.cs-CZ.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.da-DK.resx" >
<Link > Localization\Strings.da-DK.resx</Link>
</EmbeddedResource>
2017-04-08 05:20:03 +02:00
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.de-AT.resx" >
<Link > Localization\Strings.de-AT.resx</Link>
</EmbeddedResource>
2017-01-13 23:47:12 +01:00
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.de-DE.resx" >
<Link > Localization\Strings.de-DE.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.el-GR.resx" >
<Link > Localization\Strings.el-GR.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.es-ES.resx" >
<Link > Localization\Strings.es-ES.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.fi-FI.resx" >
<Link > Localization\Strings.fi-FI.resx</Link>
</EmbeddedResource>
2017-03-11 17:30:45 +01:00
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.fr-CH.resx" >
<Link > Localization\Strings.fr-CH.resx</Link>
</EmbeddedResource>
2017-01-13 23:47:12 +01:00
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.fr-FR.resx" >
<Link > Localization\Strings.fr-FR.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.he-IL.resx" >
<Link > Localization\Strings.he-IL.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.hi-IN.resx" >
<Link > Localization\Strings.hi-IN.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.hu-HU.resx" >
<Link > Localization\Strings.hu-HU.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.id-ID.resx" >
<Link > Localization\Strings.id-ID.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.it-IT.resx" >
<Link > Localization\Strings.it-IT.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.ja-JP.resx" >
<Link > Localization\Strings.ja-JP.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.ko-KR.resx" >
<Link > Localization\Strings.ko-KR.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.lt-LT.resx" >
<Link > Localization\Strings.lt-LT.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.mk-MK.resx" >
<Link > Localization\Strings.mk-MK.resx</Link>
</EmbeddedResource>
2017-02-09 13:45:31 +01:00
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.nl-BE.resx" >
<Link > Localization\Strings.nl-BE.resx</Link>
</EmbeddedResource>
2017-01-13 23:47:12 +01:00
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.nl-NL.resx" >
<Link > Localization\Strings.nl-NL.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.no-NO.resx" >
<Link > Localization\Strings.no-NO.resx</Link>
</EmbeddedResource>
2017-01-06 19:51:09 +01:00
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.pl-PL.resx" >
<Link > Localization\Strings.pl-PL.resx</Link>
2017-01-06 12:11:11 +01:00
</EmbeddedResource>
2017-01-13 23:47:12 +01:00
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.pt-BR.resx" >
<Link > Localization\Strings.pt-BR.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.pt-PT.resx" >
<Link > Localization\Strings.pt-PT.resx</Link>
</EmbeddedResource>
2017-01-06 12:11:11 +01:00
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.resx" >
<Link > Localization\Strings.resx</Link>
2017-01-13 23:47:12 +01:00
<Generator > ResXFileCodeGenerator</Generator>
<LastGenOutput > Strings.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.ro-RO.resx" >
<Link > Localization\Strings.ro-RO.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.ru-RU.resx" >
<Link > Localization\Strings.ru-RU.resx</Link>
</EmbeddedResource>
2017-03-06 21:07:10 +01:00
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.sk-SK.resx" >
<Link > Localization\Strings.sk-SK.resx</Link>
</EmbeddedResource>
2017-01-13 23:47:12 +01:00
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.sr-CS.resx" >
<Link > Localization\Strings.sr-CS.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.sr-SP.resx" >
<Link > Localization\Strings.sr-SP.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.sv-SE.resx" >
<Link > Localization\Strings.sv-SE.resx</Link>
</EmbeddedResource>
2017-01-16 01:28:44 +01:00
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.th-TH.resx" >
<Link > Localization\Strings.th-TH.resx</Link>
</EmbeddedResource>
2017-01-13 23:47:12 +01:00
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.tr-TR.resx" >
<Link > Localization\Strings.tr-TR.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.uk-UA.resx" >
<Link > Localization\Strings.uk-UA.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.vi-VN.resx" >
<Link > Localization\Strings.vi-VN.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.zh-CN.resx" >
<Link > Localization\Strings.zh-CN.resx</Link>
</EmbeddedResource>
<EmbeddedResource Include= "..\ArchiSteamFarm\Localization\Strings.zh-TW.resx" >
<Link > Localization\Strings.zh-TW.resx</Link>
2017-01-06 12:11:11 +01:00
</EmbeddedResource>
2016-08-02 12:13:15 +02:00
<EmbeddedResource Include= "BotStatusForm.resx" >
<DependentUpon > BotStatusForm.cs</DependentUpon>
</EmbeddedResource>
2016-08-02 08:50:31 +02:00
<EmbeddedResource Include= "MainForm.resx" >
<DependentUpon > MainForm.cs</DependentUpon>
</EmbeddedResource>
2016-08-02 06:13:58 +02:00
<EmbeddedResource Include= "Properties\Resources.resx" >
<Generator > ResXFileCodeGenerator</Generator>
<LastGenOutput > Resources.Designer.cs</LastGenOutput>
<SubType > Designer</SubType>
</EmbeddedResource>
<Compile Include= "Properties\Resources.Designer.cs" >
<AutoGen > True</AutoGen>
<DependentUpon > Resources.resx</DependentUpon>
2016-08-02 12:13:15 +02:00
<DesignTime > True</DesignTime>
2016-08-02 06:13:58 +02:00
</Compile>
<None Include= "packages.config" />
<None Include= "Properties\Settings.settings" >
<Generator > SettingsSingleFileGenerator</Generator>
<LastGenOutput > Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include= "Properties\Settings.Designer.cs" >
<AutoGen > True</AutoGen>
<DependentUpon > Settings.settings</DependentUpon>
<DesignTimeSharedInput > True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup >
<None Include= "App.config" />
</ItemGroup>
<ItemGroup >
2016-08-03 17:16:11 +02:00
<None Include= "FodyWeavers.xml" />
2016-08-02 12:13:15 +02:00
<None Include= "Resources\SteamUnknownAvatar.jpg" />
2016-08-02 06:13:58 +02:00
</ItemGroup>
2016-11-11 02:00:27 +01:00
<ItemGroup >
<Content Include= "..\ArchiSteamFarm\ASF.ico" >
<Link > ASF.ico</Link>
</Content>
</ItemGroup>
2016-08-02 06:13:58 +02:00
<Import Project= "$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
2016-08-27 09:34:08 +02:00
<PropertyGroup >
<PostBuildEvent Condition= " '$(OS)' != 'Unix' AND '$(ConfigurationName)' == 'Release' " >
copy "$(TargetDir)$(TargetName).exe" "$(SolutionDir)out\ASF-GUI.exe"
</PostBuildEvent>
<PostBuildEvent Condition= " '$(OS)' == 'Unix' AND '$(ConfigurationName)' == 'Release' " >
2017-02-07 21:09:08 +01:00
set -e
2017-05-08 17:32:34 +02:00
if [ -f "$(SolutionDir)mono_envsetup.sh" ]; then
. "$(SolutionDir)mono_envsetup.sh"
fi
if [ -n "$MONO_FACADES" ]; then
mono "$(SolutionDir)tools/ILRepack/ILRepack.exe" "/lib:$MONO_FACADES" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out/ASF-GUI.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
else
mono "$(SolutionDir)tools/ILRepack/ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out/ASF-GUI.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
fi
rm "$(SolutionDir)out/ASF-GUI.exe.config"
2016-08-27 09:34:08 +02:00
</PostBuildEvent>
</PropertyGroup>
2016-08-03 17:16:11 +02:00
<Target Name= "EnsureNuGetPackageBuildImports" BeforeTargets= "PrepareForBuild" >
<PropertyGroup >
<ErrorText > This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
2017-01-07 02:39:29 +01:00
<Error Condition= "!Exists('..\packages\Resource.Embedder.1.2.2\build\Resource.Embedder.targets')" Text= "$([System.String]::Format('$(ErrorText)', '..\packages\Resource.Embedder.1.2.2\build\Resource.Embedder.targets'))" />
Fix async/await with ConcurrentHashSet
Now this is a nice bug that was found accidentally by ArchiBoT...
ReaderWriterLockSlim() is very decent solution, but it's thread-based, and we're using our ConcurrentHashSet in mixed async/sync context. This means that if we use something like:
foreach (var item in concHashSet) {
await AnythingAsync().ConfigureAwait(false);
}
It's totally possible that we'll request read lock as thread 1, and release the read lock as thread 2, which will lead to RWLock exception => System.Threading.SynchronizationLockException: The read lock is being released without being held.
Fortunately it looks like we didn't have any scenario like this in ASF, as this was possible only when we async/await while enumerating over ConcurrentHashSet, so that specific bug didn't affect ASF codebase (yet). Still, I must fix this as current implementation is not thread-safe, so our HashSet is in fact not concurrent in the first place.
I analyzed possible solutions and there are basically 3: either using ConcurrentDictionary and wrapping around it, replacing lock with SemaphoreSlim, or using third-party AsyncReaderWriterLock from StephenCleary. SemaphoreSlim entirely kills the concept of multiple readers one writer, and could affect performance negatively, moreover - it doesn't support upgreadable lock scenario we have with ReplaceIfNeededWith(). Concurrent dictionary would be nice if I didn't have that awful memory hit from storing mandatory pointless value, plus I don't really like concept of wrapping around conc dictionary if I can simply use it right away and drop my conc hashset entirely. AsyncReaderWriterLock seem to be really well written, and works on Mono + should be compatible with .NET core in the future, so we should go for it as it's the best bet both performance-wise and memory-wise.
This brings another package dependency and changes a bit backend of ConcurrentHashSet
2017-02-07 20:14:51 +01:00
<Error Condition= "!Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text= "$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
2017-05-17 02:36:49 +02:00
<Error Condition= "!Exists('..\packages\Fody.2.0.8\build\netstandard1.4\Fody.targets')" Text= "$([System.String]::Format('$(ErrorText)', '..\packages\Fody.2.0.8\build\netstandard1.4\Fody.targets'))" />
2016-08-03 17:16:11 +02:00
</Target>
2017-01-07 02:42:37 +01:00
<Import Project= "..\packages\Resource.Embedder.1.2.2\build\Resource.Embedder.targets" Condition= "'$(OS)' != 'Unix' AND '$(ConfigurationName)' == 'Release' AND Exists('..\packages\Resource.Embedder.1.2.2\build\Resource.Embedder.targets')" />
Fix async/await with ConcurrentHashSet
Now this is a nice bug that was found accidentally by ArchiBoT...
ReaderWriterLockSlim() is very decent solution, but it's thread-based, and we're using our ConcurrentHashSet in mixed async/sync context. This means that if we use something like:
foreach (var item in concHashSet) {
await AnythingAsync().ConfigureAwait(false);
}
It's totally possible that we'll request read lock as thread 1, and release the read lock as thread 2, which will lead to RWLock exception => System.Threading.SynchronizationLockException: The read lock is being released without being held.
Fortunately it looks like we didn't have any scenario like this in ASF, as this was possible only when we async/await while enumerating over ConcurrentHashSet, so that specific bug didn't affect ASF codebase (yet). Still, I must fix this as current implementation is not thread-safe, so our HashSet is in fact not concurrent in the first place.
I analyzed possible solutions and there are basically 3: either using ConcurrentDictionary and wrapping around it, replacing lock with SemaphoreSlim, or using third-party AsyncReaderWriterLock from StephenCleary. SemaphoreSlim entirely kills the concept of multiple readers one writer, and could affect performance negatively, moreover - it doesn't support upgreadable lock scenario we have with ReplaceIfNeededWith(). Concurrent dictionary would be nice if I didn't have that awful memory hit from storing mandatory pointless value, plus I don't really like concept of wrapping around conc dictionary if I can simply use it right away and drop my conc hashset entirely. AsyncReaderWriterLock seem to be really well written, and works on Mono + should be compatible with .NET core in the future, so we should go for it as it's the best bet both performance-wise and memory-wise.
This brings another package dependency and changes a bit backend of ConcurrentHashSet
2017-02-07 20:14:51 +01:00
<Import Project= "..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition= "Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
2017-05-17 02:36:49 +02:00
<Import Project= "..\packages\Fody.2.0.8\build\netstandard1.4\Fody.targets" Condition= "'$(OS)' != 'Unix' AND '$(ConfigurationName)' == 'Release' AND Exists('..\packages\Fody.2.0.8\build\netstandard1.4\Fody.targets')" />
2016-08-02 06:13:58 +02:00
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name= "BeforeBuild" >
</Target>
<Target Name= "AfterBuild" >
</Target>
-->
</Project>