RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / user-196257

Monk's questions

Martin Hope
Monk
Asked: 2022-05-10 00:26:55 +0000 UTC

如果 DI 容器不能离开组合根,如何声明生命周期范围?

  • 4

我正在阅读“.NET Platform 2nd Edition 上的依赖注入”(俄语,春季发布)。作者清楚地写了几次-

使用 DI 容器时,组合根必须是使用该容器的唯一位置。在组合根之外使用 DI 容器会导致 Service Locator 反模式,这将在下一章中讨论。

举个例子,说明它很丑。好吧,假设我同意。

我有一个 WPF(或任何其他)桌面应用程序。我认为每次按下 UI 中的某个“按钮”都是一个单独范围内的操作。那些。API 的一部分应该创建与生命相对应的实例。通常,在 ICommand.Execute 处理程序中,有以下伪代码:

void ICommand.Execute(object parameter)
{
  using (DI.CreateSomeScope())
    new SomeCommand(...).Execute(parameter);
}

有两个问题,第一个很重要,第二个在评论中整理出来,但也许有人对这个问题有自己的看法 - 也分享一下:

  • 我怎样才能在这里声明一个范围?根据本书和大多数 DI 框架,范围完全是容器的责任。将它拖到这里是一个显式的服务定位器。
  • 怎么办new SomeCommand?嗯,即 例如,程序的主窗口已经在运行,我想要的一切都显示出来了。然后用户点击“设置”。我需要创建一个设置 VM,然后将其分配给一个 binned 属性以更改应用程序。并且 DI 再次负责创建不稳定的(vm 非常适合不稳定的)依赖项。我真的不明白如何在应用程序生命周期的中间实例化对象。在书中,作者主要展示了基本的例子,或者是aspnet,其中有一个预谋的点——创建一个控制器来处理请求。
c#
  • 1 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-03-31 17:57:58 +0000 UTC

规范化文件夹或文件的路径

  • 2

需要根据业务实体的名称在其中创建文件夹和子文件夹,使名称尽可能接近原始名称。

同时还要考虑到操作系统的限制,这就增加了麻烦——如果linux-macos实际上没有限制,那么在windows上就绰绰有余了。

结果是这段代码,无效字符被替换为点。

private static readonly string NormalizationPattern = string.Format(@"([{0}]*\.+$)|([{0}]+)", Regex.Escape(string.Concat(new string(Path.GetInvalidPathChars()), "?", "/", "*", "\"")));
private static readonly string[] DosReservedNames = { "CON", "PRN", "AUX", "NUL", "COM0", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9" };

public static string NormalizePath(string name)
{
  if (Environment.OSVersion.Platform == PlatformID.Unix ||
      Environment.OSVersion.Platform == PlatformID.MacOSX)
    return name;

  const string replacement = ".";
  var matchesCount = Regex.Matches(name, @":\\").Count;
  string correctName;
  if (matchesCount > 0)
  {
    var regex = new Regex(@":", RegexOptions.RightToLeft);
    correctName = regex.Replace(name, replacement, regex.Matches(name).Count - matchesCount);
  }
  else
    correctName = name.Replace(":", replacement);

  var replace = Regex.Replace(correctName, NormalizationPattern, replacement);
  foreach (var reservedName in DosReservedNames)
  {
    var builder = new List<string>();
    foreach (var folder in replace.Split(Path.DirectorySeparatorChar))
    {
      var changedName = folder;
      if (string.Equals(folder, reservedName, StringComparison.InvariantCultureIgnoreCase))
        changedName = replacement + reservedName;

      var value = reservedName + '.';
      if (folder.StartsWith(value, StringComparison.InvariantCultureIgnoreCase))
        changedName = replacement + value + folder.Remove(0, value.Length);

      builder.Add(changedName);
    }

    replace = string.Join<string>(Path.DirectorySeparatorChar.ToString(), builder);
  }
  return replace.TrimEnd(' ', '.');
}

文件夹根目录通常由系统选择并且已经存在。然后通过规范化创建所有嵌套级别。因此,例如,点和空格的修剪只在最后完成,而不是在每个级别。也许你不应该这样做,你应该修剪每个文件夹的名称。

为所有这些编写测试,整个案例如下所示:

[Test, Sequential]
public void CheckNotAllowedNames([Values(
  "test"
  ,@"C:\somename\somename:name"
  ,@"usr\home\somename:name"
  ,@"start < > : "" / \ | ? * end"
  ,"\x15\x3D" // less than ASCII space
  ,"\x21\x3D" // HEX of !, valid
  ,"\x3F\x3D" // HEX of ?, not valid
  ,@"C:\somename\   trailing space   "
  ,@"C:\somename\...trailing period..."
  ,@"C:\somename\CON"
  ,@"C:\somename\CON.txt"
  ,@"CON"
  ,@"C:\somename\con.txt\context"
  ,@"home\NUL.liza"
  ,@"home\ NUL.liza"
  ,@"C:\somename\..." // Bad name get the root folder, bug =_=
  ,@"root\..\sub"
  ,@"root\..\"
  ,@".\..\some?folder"
  ,@"root\.." // relative path trimmed, bug =_=
)] string name, [Values(
  "test"
  ,@"C:\somename\somename.name"
  ,@"usr\home\somename.name"
  ,@"start . . . . . \ . . . end"
  ,".="
  ,"!="
  ,".="
  ,@"C:\somename\   trailing space"
  ,@"C:\somename\...trailing period"
  ,@"C:\somename\.CON"
  ,@"C:\somename\.CON.txt"
  ,@".CON"
  ,@"C:\somename\.CON.txt\context"
  ,@"home\.NUL.liza"
  ,@"home\ NUL.liza"
  ,@"C:\somename\"
  ,@"root\..\sub"
  ,@"root\..\"
  ,@".\..\some.folder"
  ,@"root\"
)] string expected)
{
  Assert.AreEqual(expected, NormalizePath(name));
}

实际上,首先,我希望有人可以查看并找出我错过的错误。

其次 - 也许我正在重新发明轮子,哪里有现成的标准化?我用谷歌搜索了很久,但我可能会错过,周围有很多自行车。


UPD1:发现了相对路径的问题,我仍然不知道如何解决,我添加了当前行为的测试。dotnet API 允许您请求创建文件夹root\folder\.....并返回root. msdn上的帮助说可以通过api创建积分,但是不应该,以免造成问题。最后如何更正确地处理相对路径是另一个问题。

c#
  • 1 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-11-29 01:51:03 +0000 UTC

如何使代码上下文敏感,但不显式传递上下文?

  • 4

现在是什么:

public static Page GetPage(Uri url)

你需要什么:

限制某些“上下文”内的请求数量。

  1. 这可以是 url 参数中的主机(这是最简单的选项,您可以只写下当前主机和限制)
  2. 可能有一个“站点”在不同的云提供商实例上托管不同的东西,您无法通过主机将它们区分开来。
  3. 可能有一个程序集请求一个方法(即一个程序集,例如,使用此方法一次不能接收超过 3 个不同的页面)
  4. 可能有一个方法(该方法不应该,例如并行发出大量请求),虽然它可能包含在以前的版本中,但我还没有仔细考虑过。

总的来说,一方面我希望当我做一个条件的时候godObject.Download(),他在里面做一些他自己的检查,加上下载,再加上一些其他的东西,这样里面就不会出现一堆并行请求,另一方面,这样当我这样做simpleClass.DownloadAllLinks()时,他可以并行处理一组链接,如果它们位于不同的资源上。


这大致被视为一个属性Request,它几乎总是存在于 Web 服务器中,因为 请求处理是整个生命周期。无论如何,我也有某种应用程序周期,例如,用户按下按钮(但不幸的是,它不会成为下载页面的上下文)。但我仍然无法将它们放在某种合乎逻辑的方案中。

我不想将方法重新制作为非静态的,因为它已经在许多地方使用,并且不容易显式地到达那里,例如“上下文”的实例。

c#
  • 2 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-10-07 22:33:11 +0000 UTC

构建依赖和构建

  • 2

有一个桌面解决方案(4.6 和网络标准 2.0),其中实际上存在三个级别的依赖关系——共享程序集(内核)、UI 程序集和插件(更准确地说,有几个,但它们是在依赖性方面相同)。

UI 程序集依赖于内核,正常构建在需要时成功复制程序集,不幸的是排除了本机依赖项。插件仍然更难过,因为。它们依赖于内核,但没有人应该知道它们,不能使用标准依赖项。

现在构建部分由 beforebuild 事件保证,但由于 不相关的项目可以按不同的顺序编译,有时你必须愚蠢地编译两次。另外,现在它是使用 xcopy 完成的,但我想要一个跨平台的构建。

据我了解,目标文件有一个选项,但除了文章https://rsdn.org/article/devtools/msbuild-05.xml#EVGAE之外,我没有找到任何有意义的帮助

另外,还有像 Cake (C# Make) 这样的不同的东西,但实际上这是一个单独的工具,你必须学习如何使用,而且这些解决方案的跨平台性也不清楚。

一般来说,你需要一些流行的解决方案,它有很好的dock,并且可以在没有拐杖的情况下做典型的解决方案(这样你就不必手动编写msbuild来构建项目)。


它现在的样子的一个例子。实线是明确的依赖关系,虚线是隐含的依赖关系,您必须在拐杖上从不同的文件夹复制到不同的文件夹。 在此处输入图像描述

c#
  • 1 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-07-07 20:15:48 +0000 UTC

在 NHibernate 的 OnFlushDirty 事件中更改实体

  • 5

有一个“设置”实体存储数据的路径。有些实体使用设置来构建其数据路径。

我想在更改设置时验证其他实体的路径,并在必要时重新保存它们。我是如何尝试的:

  1. 重叠Interceptor并捕获事件OnFlushDirty,它允许您捕获所需属性的变化:

    var folderIndex = propertyNames.ToList().IndexOf(nameof(Folder));
    if (folderIndex > -1 && previousState != null)
    {
      var previous = previousState[folderIndex] as string;
      var current = currentState[folderIndex] as string;
      if (previous != current)
      {
        var someEntities = session.Query<ISomeEntity>().Where(m => m.Setting == this).ToList();
        foreach (var someEntit in someEntities)
        {
          someEntity.RefreshFolder();
        }
      }
    }
    

计算结果是,由于更改在会话内部(已经在事务提交中),因此将自动获取更改。没有帮助。如果someEntity.RefreshFolder();添加session.SaveOrUpdate(someEntity)之后,奇迹不会发生,实体也不会被保存。

  1. 在外部,设置调用包含在事务中:

    using (var tranc = session.OpenTransaction())
    {
      try
      {
        session.SaveOrUpdate(setting);
        tranc.Commit();
      }
      catch (System.Exception)
      {
        tranc.Rollback();
        throw;
      }
    }
    
  2. 如第 1 点所示,有SomeEntity一个指向 的链接Setting,如果我尝试进行单独的交易,那么它会转到 SO,因为 保存的设置成为保存实体所必需的,它将导致再次保存实体。

  3. 所有会话都启用了它session.FlushMode = FlushMode.Commit,以便会话中的随机更改(例如,稍后通过异常验证)不会尝试将其保存到数据库中。

一般来说,我希望设置中更改文件夹的操作是事务性的,因为如果不是,那么您可以在事务完成后简单地执行相同的操作,而无需将它们相互链接,但是不再可能了以保证数据的有效性。

c#
  • 1 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-12-24 18:46:43 +0000 UTC

如何使异步 IEnumerable?

  • 8

我正在同时在几个地方进行搜索。

目前,在顶层,类似:

  foreach (var item in Plugins.SelectMany(p => p.Search(query)))
    Items.Add(new ViewModel(item));

在 Search 方法的每个实现中:

public override IEnumerable<Item> Search(string name)
{
  await some resource
  foreach (var element in networkResult)
    ...
    yield return result;
}

事实上,我希望并行访问所有搜索,以便每个元素在准备就绪时出现在 UI 中,而不是在整个事情结束时出现,因为它目前可以工作。究竟要在这里包含什么任务 - 没有好主意。在外面,它似乎更合乎逻辑Task<IEnumerable>,但我不明白如何正确实现它。

c#
  • 1 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-11-08 23:20:12 +0000 UTC

如何形成类似于用代码编写的表达式?

  • 2

我目前有这样的代码:

public override Expression<Func<ITask, TaskDto>> ConvertEntityToDto()
{
  return t => t.TypeDiscriminator == guid ? new SimpleTaskDto((ISimpleTask)t) : new TaskDto(t);
}

它工作得很好,有时SimpleTaskDto,有时TaskDto,一切都按预期返回。

事实上,我想让它变得更难一些 - 返回对 fooGuid - FooTaskDto known in runtime ,FooTaskDto对于未知的 - TaskDto。

这可以使用表达式构建吗?如果没有,有哪些选择?

底线是,这是实体从 base 到 Dto 转换的一部分,如果我选择了错误的类型,那么我会丢失一些有用的字段,这迫使我提出单独的请求,尽管我本可以做到它就在这里。

c#
  • 1 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-10-12 07:23:23 +0000 UTC

如何将 Automapper Collection 用于嵌套集合?

  • 2

我使用AutoMapper.Collection 3.1.2(和AutoMapper 6.0.2)

A从 ORM 中,B您不能简单地在其中重新创建集合。实际上,这正是您所需要AutoMapper.Collection的。

映射是根据 github 主页上的说明构建的AutoMapper.Collection,它说只是为了映射,Mapper.Map<OrderDTO[],Order[]>(orderDtos, orders);我尝试做同样的事情,但没有任何效果:

  [TestFixture]
  public class UnitTest1
  {
    [Test]
    public void TestMethod1()
    {
      AutoMapper.Mapper.Initialize(cfg =>
      {
        cfg.AddCollectionMappers();
        cfg.CreateMap<ADto, A>().EqualityComparison((dto, a) => dto.Name == a.Name);
        cfg.CreateMap<BDto, B>().EqualityComparison((dto, b) => dto.Name == b.Name);
      });

      var aDto = new ADto(){Name = "A", Container = new List<BDto>()};
      aDto.Container.Add(new BDto(){Name = "B"});
      var aObj = new A(){ Name = "A" };

      var dtos = new [] {aDto};
      var objs = new [] {aObj};

      AutoMapper.Mapper.Map(dtos, objs);
      Assert.IsNotEmpty(aObj.Container);
    }
  }

  public class ADto
  {
    public string Name { get; set; }

    public ICollection<BDto> Container { get; set; }
  }

  public class BDto
  {
    public string Name { get; set; }
  }

  public class A
  {
    public string Name { get; set; }

    public ICollection<B> Container { get; set; }

    public A() { this.Container = new List<B>(); }
  }

  public class B
  {
    public string Name { get; set; }
  }

那些。有一个ADto名称为“A”,还有A一个名称相同的对象。映射器应该弄清楚这是同一个对象(为什么要另外指定EqualityComparison?)并同步它们的集合。

c#
  • 1 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-09-02 17:29:48 +0000 UTC

如何确保正确排序文件夹

  • 9

假设有从1到8的章节。稍后,作者添加了7.5的条件奖金。

现在,我想做一些比较统一的章节命名,最初的想法是“0001章”。排序工作稳定(只要章节少于 10k,是的)排序直到出现奖励章节。

有没有人对如何命名章节有任何好主意,以便奖金(尤其是那些追溯添加的)不会破坏排序并落到最后或中间的某个地方?

PS:特别有趣的是,名称中的句点在//和这些操作系统上的不同应用程序中win排序unix不同android。

файлы
  • 5 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-08-11 00:44:35 +0000 UTC

与 nhibernate 异步工作的选项有哪些?

  • 1

我正在修补 petproject,我用nhibernate它来存储数据。

Nhibernate开箱即用,它不知道如何异步,但原则上我有足够async-await的能力让它中断并开始写入保存操作:

NHibernate.HibernateException: 非法尝试将集合与 NHibernate.Event.Default 中 NHibernate.Event.Default.OnUpdateVisitor.ProcessCollection(Object collection, CollectionType type) 中 NHibernate.Collection.AbstractPersistentCollection.SetCurrentSession(ISessionImplementor session) 中的两个打开会话相关联。 AbstractVisitor.ProcessValue(Object value, IType type) to NHibernate.Event.Default.AbstractVisitor.ProcessValue(Int32 i, Object[] values, IType[] types) to NHibernate.Event.Default.AbstractVisitor.ProcessEntityPropertyValues(Object[] values, IType[] types) 到 NHibernate.Event.Default.AbstractVisitor.Process(Object obj, IEntityPersister persister) 到 NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.PerformUpdate(SaveOrUpdateEvent 事件, 对象实体,IEntityPersister 持久化)到 NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsDetached(SaveOrUpdateEvent 事件)到 NHibernate.Event.Default.DefaultUpdateEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent 事件)到 NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveImiberUpdate.eventUpdate(SaveImiberUpdate.event)Ornate SessionImpl NHibernate.Impl.SessionImpl.Update(Object obj) 中的 .FireUpdate(SaveOrUpdateEvent 事件)...NHibernate.Impl.SessionImpl.Update(Object obj) 中的 FireUpdate(SaveOrUpdateEvent 事件)...NHibernate.Impl.SessionImpl.Update(Object obj) 中的 FireUpdate(SaveOrUpdateEvent 事件)...

Heber 设置为CurrentSessionContext<ThreadLocalSessionContext>(),即 据我了解 - 在流上的会话。所有选项似乎都对我没有帮助,或者我不理解帮助。

因此,问题是:

如何在异步应用程序中使用 hiber?同步通话?从会话中取消挂钩对象并将它们挂钩到每个线程中的正确对象?(这实际上会丢弃整个一级缓存)。

c#
  • 1 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-08-02 19:02:09 +0000 UTC

如何获取日期和时间的特定分支(或提交哈希)?

  • 1

您需要获取特定时间的 git 存储库的状态。当前的实现使用在一堆答案中的 SO 上找到的选项来获得提交,然后我们检查:

rev-list -n 1 --before="{datetime}" {branch}

它在 master 分支上运行良好,但在 feature 分支上存在问题,master 有时会在其中增长。对于这样的分支,返回来自 master 的提交哈希,这显然将我们切换到 master 状态。

阅读帮助提出了--first-parent option ,但我不确定它不会有其他我还没有偶然发现的问题。

所以我当前的版本是这样的:

rev-list -n 1 --first-parent --before="{datetime}" {branch}

我需要有关如何最好地请求此信息以及我在当前请求中缺少的内容的建议。

git
  • 1 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-04-30 23:11:45 +0000 UTC

使文本中的链接可点击

  • 1

我用ListView它来显示日志。有时日志中有链接(例如,“无效链接:http ://example.com/ ”),我只想点击它们,它们会在普通浏览器中打开。

这可以自动完成,还是必须手动解析并转换为 和 的Run组合Hyperlink?

c#
  • 2 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-04-02 15:43:40 +0000 UTC

为什么异步代码中的异常被认为是未处理的?

  • 3

有一个下载文件的代码,在较低级别有一个简单的循环,限制了多次下载尝试,它看起来像这样简化:

private static bool Failed = false;

static void Main(string[] args)
{
  TaskScheduler.UnobservedTaskException += (o, a) => { throw a.Exception; };
  ChapterDownload().Wait();
}

public static async Task ChapterDownload()
{
  try
  {
    var pages = Enumerable.Range(0, 20);
    var pTasks = pages.Select(page =>
    {
      return PageDownload()
      .ContinueWith(t => Console.WriteLine("{0}{1}", t.Status, t.IsFaulted));
    });
    await Task.WhenAll(pTasks.ToArray());
  }
  catch (Exception ex)
  {
    //
  }
}

public static async Task PageDownload()
{
  if (Failed)
    throw new Exception("boom");

  try
  {
    // var file = await new WebClient().DownloadDataTaskAsync(new Uri(@"http://example.com"));
    var file = await DownloadFile(new Uri(@"http://example.com"));
    if (file != null)
      throw new Exception("Restart download, downloaded file is corrupted");
  }
  catch (Exception ex)
  {
    Failed = true;
    await PageDownload();
  }
}

public static async Task<byte[]> DownloadFile(Uri uri)
{
  byte[] result;
  WebResponse response;
  var request = WebRequest.Create(uri);

  try
  {
    response = await request.GetResponseAsync();
    using (var memory = new MemoryStream())
    {
      await response.GetResponseStream().CopyToAsync(memory);
      result = memory.ToArray();
    }
  }
  catch (System.Exception ex)
  {
    return null;
  }
  if (response.ContentLength == result.LongLength)
    return result;
  return null;
}

问题是 - 在当前形式下,它发生UnobservedTaskException在 textboom上,即 显然是我的。同时,如果我将自制下载替换为webclient-UnobservedTaskException它不再发生。有什么区别?

c#
  • 1 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-03-25 18:09:26 +0000 UTC

如何确定多线程程序中的下载速度?

  • 7

有一个简单的下载代码:

internal static async Task<ImageFile> DownloadFile(Uri uri)
{
  byte[] result;
  WebResponse response;
  var file = new ImageFile();
  var request = WebRequest.Create(uri);

  try
  {
    response = await request.GetResponseAsync();
    using (var ms = new MemoryStream())
    {
      response.GetResponseStream().CopyTo(ms);
      result = ms.ToArray();
    }
  }
  catch (System.Exception ex) { }
  if (response.ContentLength == result.LongLength)
    file.Body = result;
  return file;
}

我想添加一个下载速度指示器。谷歌建议你可以关注阅读流的速度:

result = await CopyTo(response.GetResponseStream(), response.ContentLength, progressChanged);

private static async Task<byte[]> CopyTo(Stream from, long totalBytes, Action<DownloadProgress> loadedEvent)
{
  var sw = new Stopwatch();
  sw.Start();
  var data = new byte[totalBytes];
  byte[] buffer = new byte[81920];
  int currentIndex = 0;
  while (true)
  {
    int num = await from.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
    if (num != 0)
    {
      Array.Copy(buffer, 0, data, currentIndex, num);
      currentIndex += num;
      loadedEvent?.Invoke(new DownloadProgress(currentIndex, totalBytes, sw.ElapsedMilliseconds));
    }
    else
      break;
  }
  sw.Stop();
  return data;
}

为了存储信息(并向上滚动),我开始了一个简单的结构:

public struct DownloadProgress
{
  public readonly long BytesReceived;

  public readonly long TotalBytesToReceive;

  public readonly long TimeMs;

  public double GetSpeed()
  {
    var seconds = TimeMs / 1000.0;
    if (seconds > 0)
      return BytesReceived / seconds;
    return 0;
  }

  public DownloadProgress(long received, long total, long time)
  {
    this.BytesReceived = received;
    this.TotalBytesToReceive = total;
    this.TimeMs = time;
  }
}

总的来说,如果你在一个流中下载,那么GetSpeed在任何时候(除了某处的第一秒)它都会显示真实速度。

下载总图的类最终存储:

    this.Speed = 0;
    var file = await ImageFile.DownloadFile(this.ImageLink, dp => this.Speed = dp.GetSpeed());
    this.Speed = 0;

然后我认为剩下的是最简单的 - 我只是在顶层添加了所有速度,仅此而已:

return this.ActivePages != null && this.ActivePages.Any() ? 
  this.ActivePages.Sum(p => p.Speed) : 0;

事实上,结果是非常不愉快的行为:

  1. 大多数时候速度实际上是正确显示的。

  2. 速度经常跳跃,点差有时超过通道宽度。对于 650 kb/s 的信道,数字从 300 kb/s 跃升至 5-8 Mb/s。

如果在一次下载结束和下一次下载开始时速度很可能较低,那么从技术上讲,超过通道宽度显然是不可能的。也许我错过了某处的四舍五入,或者Stopwatch对于这样的计算来说不够准确?

UPD:第一个怀疑是有道理的——最初的速度跳跃破坏了整体统计数据。如果速度计算方法是这样进行的:

  public double GetSpeed()
  {
    var seconds = TimeMs / 1000.0;
    if (seconds > 0.1)
      return BytesReceived / seconds;
    return 0;
  }

那个速度一般就够用了,偶尔也会有超过通道宽度的跳跃,但不会超过5%。你可以增加被忽略的时间,这样就完全没有跳跃了。

总分有问题。如果对于一个流,该数字是可靠的,那么对于多线程下载,该数字通常是谎言,指标的平均值结果低于真实值(总时间为总容量)。

UPD2:最小化所有计算,删除结构,将逻辑移至静态类:

  public class NetworkSpeed
  {
    public static double TotalSpeed { get { return totalSpeed; } }

    private static double totalSpeed = 0;

    private const uint Seconds = 3;

    private const uint TimerInterval = 1000;

    private static Timer speedTimer = new Timer(state =>
    {
      var now = 0L;
      while (receivedStorage.Value.Any())
      {
        long added;
        if (receivedStorage.Value.TryDequeue(out added))
        {
          now += added;
        }
      }
      lastSpeeds.Value.Enqueue(now);
      totalSpeed = lastSpeeds.Value.Average();
    }, null, 0, TimerInterval);

    private static Lazy<LimitedConcurrentQueue<double>> lastSpeeds = new Lazy<LimitedConcurrentQueue<double>>(() => new LimitedConcurrentQueue<double>(Seconds));

    private static Lazy<ConcurrentQueue<long>> receivedStorage = new Lazy<ConcurrentQueue<long>>();

    public static void Clear()
    {
      while (receivedStorage.Value.Count > 0)
      {
        long dd;
        receivedStorage.Value.TryDequeue(out dd);
      }
      while (lastSpeeds.Value.Count > 0)
      {
        double dd;
        lastSpeeds.Value.TryDequeue(out dd);
      }
    }

    public static void AddInfo(long received)
    {
      receivedStorage.Value.Enqueue(received);
    }

    private class LimitedConcurrentQueue<T> : ConcurrentQueue<T>
    {
      public uint Limit { get; }

      public new void Enqueue(T item)
      {
        while (Count >= Limit)
        {
          T deleted;
          TryDequeue(out deleted);
        }
        base.Enqueue(item);
      }

      public LimitedConcurrentQueue(uint limit)
      {
        Limit = limit;
      }
    }
  }

结果,在下载时,报告下一时刻下载了多少字节就足够了:

      NetworkSpeed.AddInfo(num);

就是这样,指示器NetworkSpeed.TotalSpeed将显示过去 3 秒内的平均速度。平均指标总体上或多或少变得稳定,尽管它略微高估了我数据中的指标。好吧,很明显,如果线程池过载,那么计时器将无法及时计时,速度将开始“跳跃”。

c#
  • 1 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-03-14 23:40:55 +0000 UTC

考虑到网络和磁盘,如何正确编写文件上传?

  • 0

有一段代码只是用来Parallel.ForEach以某种方式并行化下载,它看起来像这样:

Parallel.ForEach(books)
-Parallel.ForEach(chapters)
--Download(page)
--Save(page)

那些。可以在每个顶级元素上并行启动任意数量的下载,所有内容都在狭窄的通道上下垂,并且您经常会超时。当下载同时开始也几乎同时结束并尝试并行写入磁盘时,情况会更糟。

现在我有一个主要问题 - 如果你这样做更好:

var tasks = books
.SelectMany(b => b.Chapters)
.SelectMany(c => c.Pages)
.Select(p => Task.Run(() => p.Download(); p.Save())
tasks.WaitAll();

在哪种情况下网络和磁盘上的负载将是最佳的?网络还是比较关键的,因为超时不得不重复下载操作。

更新:我通过任务做了一个变体——最多 200 页可以轻松地同时下载 30 次。同时,一半以上处于Blocking状态,下载完成。活动任务的数量仍然没有自动限制,或者什么?最好的方法是什么?

UPDATE2:下载代码:

internal static ImageFile DownloadFile(Uri uri)
{
  byte[] result;
  WebResponse response;
  var file = new ImageFile();
  var request = WebRequest.Create(uri);

  try
  {
    response = request.GetResponse();
    using (var ms = new MemoryStream())
    {
      response.GetResponseStream().CopyTo(ms);
      result = ms.ToArray();
    }
  }
  catch (System.Exception ex)
  {
    Log.Exception(ex, string.Format("Загрузка {0} не завершена.", uri));
    return file;
  }
  if (response.ContentLength == result.LongLength)
    file.Body = result;
  return file;
}

有被阻止的任务挂起,还有一些从下面工作的任务: 在此处输入图像描述

被阻止的有这个堆栈: 在此处输入图像描述

c#
  • 1 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-01-18 22:50:40 +0000 UTC

独立于平台和语言的进程间通信

  • 1

我需要一个关于进程间通信组织的建议:

  • 不依赖于操作系统的东西,或者至少有适用于 PC (win\unix) 的工作实现
  • 如果可能 - 能够连接另一种语言 - 例如 pluses 或 python
  • 至少以字节数组形式驱动信息的能力,尽管使用某种结构会更好

实际上 - 我想要最接近指定功能的技术名称和最小的工作示例,您可以链接到某个存储库。

c#
  • 2 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-10-24 00:21:00 +0000 UTC

Abort\Retry\Ignore 在代码中的任何一点都能够将选择转储给用户

  • 14

在处理网络和 IO 时,通常存在即使对于用户(尽管是有经验的用户)也很容易解决的限制,但很难提前了解它们。繁忙的文件,不稳定的连接 - 我经常错过重复按钮,尤其是当整个过程需要并回滚时。

到目前为止,我已经为这个问题实施了一个或多或少通用的解决方案:

  public enum ExceptionHandle
  {
    Abort,
    Retry,
    Ignore
  }

  public class ExceptionEventArgs
  {
    public Exception Exception { get; }

    public ExceptionHandle? Handled { get; set; }

    public ExceptionEventArgs(Exception ex)
    {
      this.Exception = ex;
    }
  }

  public static class ExceptionHandler
  {
    public static event EventHandler<ExceptionEventArgs> Handler;

    public static void TryExecute(Action action)
    {
      TryExecute(() => { action(); return true; }, false);
    }

    public static T TryExecute<T>(Func<T> action, T whenIgnored)
    {
      ExceptionHandle? handled = ExceptionHandle.Retry;
      while (handled == ExceptionHandle.Retry)
      {
        try
        {
          return action();
        }
        catch (Exception ex)
        {
          handled = OnHandler(new ExceptionEventArgs(ex));
          if (handled.HasValue)
          {
            switch (handled.Value)
            {
              case ExceptionHandle.Abort:
                throw;
                break;
              case ExceptionHandle.Retry:
                break;
              case ExceptionHandle.Ignore:
                break;
              default:
                throw new ArgumentOutOfRangeException();
            }
          }
          else
          {
            throw;
          }
        }
      }
      return whenIgnored;
    }

    private static ExceptionHandle? OnHandler(ExceptionEventArgs e)
    {
      if (Handler == null || !Handler.GetInvocationList().Any())
      {
        ExceptionDispatchInfo.Capture(e.Exception).Throw();
      }
      else
      {
        Handler.Invoke(null, e);
      }
      return e.Handled;
    }
  }

因此,任何订户ExceptionHandler.Handler都可以自动解决问题,或者将解决方案转交给用户。现在可以包装任何危险代码:

      var tested = ExceptionHandler.TryExecute(() =>
      {
        using (var destination = new MemoryStream())
        {
          using (Stream stream = entry.Open())
            stream.CopyTo(destination);
          return destination.Length == entry.Length;
        }
      }, false);

总的来说,目前的实施在我看来已经可以忍受并且有效。但是,我怀疑这样的解决方案已经存在于某个地方,我只是找不到它们。有人可以建议从哪里获得或至少查看现成的解决方案吗?好吧,如果我的代码中有门框,我也不会拒绝帮助。

UPD:是的,我知道即使这样也有问题的情况 - 操作可以是一次性的(关闭连接,破坏 sql 会话,无论你想做什么)。它已经留在使用代码的人的良心上。虽然,我也会为这个问题寻找有趣的选项,但你会限制相同的无花果。

UPD2:我还没弄清楚是否有可能将一个这样的块包装到另一个块中,否则现在,结果是,当内部块被中止时,外部块再次进行处理。

c#
  • 3 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-10-22 15:59:11 +0000 UTC

Windows7 任务栏上不显示不确定状态

  • 3

问题的简单再现。创建一个窗口,指定:

  <Window.TaskbarItemInfo>
    <TaskbarItemInfo ProgressState="Indeterminate"/>
  </Window.TaskbarItemInfo>

我们从 Windows7 开始——面板上没有任何显示。

我们在Windows10中启动——面板上出现了预期的运行状态栏。

c#
  • 1 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-10-19 16:36:48 +0000 UTC

将项目复制到具有项目版本号的文件夹

  • 4

我想像现在浏览器一样使用应用程序的版本控制——整个新旧版本都在子文件夹中,只有一个简单的启动器决定运行哪个:

浏览器文件夹中包含内容的图像

问题 - 是否有可能在构建事件的项目中(组装前,组装后,理论上无关紧要)如何指定不复制到特定子文件夹,而是复制到与项目当前版本相对应的子文件夹?如果没有其他选择,对没有第三方实用程序和有第三方实用程序的实现感兴趣。

c#
  • 1 个回答
  • 10 Views
Martin Hope
Monk
Asked: 2020-09-05 22:48:07 +0000 UTC

如何正确转发一个异步请求到最上面?[复制]

  • 2
这个问题已经在这里得到回答:
是否可以为异步方法创建包装类? (1 个回答)
6 年前关闭。

有一个用于访问存储库的 api,它看起来像这样:

var storage = await Storages.GetLatest(id);

我需要他的文件 -storage.Files.Where(...)

其实,怎么设计一个view api通过storage id和file filter来获取文件更符合逻辑呢?

Task<IEnumerable<IFile>> GetFilesAsync(storateId, filter)

或者

IEnumerable<IFile> GetFiles(storageId, filter)

我不明白,如果我只能从存储中获取文件模型,异步存储请求会有什么好处,还需要等待吗?

c#
  • 1 个回答
  • 10 Views

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5