我需要以编程方式从我的Google Chrome扩展程序中将多个脚本文件(后跟代码段)注入当前页面.该chrome.tabs.executeScript方法允许单个InjectDetails对象(表示脚本文件或代码片段),以及在脚本之后执行的回调函数.目前的答案提出嵌套executeScript调用:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, { file: "jquery.js" }, function() {
chrome.tabs.executeScript(null, { file: "master.js" }, function() {
chrome.tabs.executeScript(null, { file: "helper.js" }, function() {
chrome.tabs.executeScript(null, { code: "transformPage();" })
})
})
})
});
Run Code Online (Sandbox Code Playgroud)
但是,回调嵌套变得难以处理.有没有办法抽象这个?
javascript google-chrome google-chrome-extension content-script
我试图找到一种直观的方法来强制表中两列的相互唯一性.我不是在寻找复合唯一性,其中不允许重复的密钥组合 ; 相反,我想要一个规则,其中任何一个键都不能再出现在任一列中.请看以下示例:
CREATE TABLE Rooms
(
Id INT NOT NULL PRIMARY KEY,
)
CREATE TABLE Occupants
(
PersonName VARCHAR(20),
LivingRoomId INT NULL REFERENCES Rooms (Id),
DiningRoomId INT NULL REFERENCES Rooms (Id),
)
Run Code Online (Sandbox Code Playgroud)
一个人可以选择任何房间作为他们的起居室,任何其他房间作为他们的餐厅.一旦房间被分配给乘客,它就不能再被分配给另一个人(无论是作为起居室还是作为餐厅).
我知道这个问题可以通过数据规范化来解决; 但是,我无法更改架构,对架构进行重大更改.
更新:回应提议的答案:
两个独特的约束(或两个唯一索引)不会阻止重复横跨两列.同样的,一个简单的LivingRoomId != DiningRoomId检查约束不会阻止跨重复行.例如,我希望禁止以下数据:
INSERT INTO Rooms VALUES (1), (2), (3), (4)
INSERT INTO Occupants VALUES ('Alex', 1, 2)
INSERT INTO Occupants VALUES ('Lincoln', 2, 3)
Run Code Online (Sandbox Code Playgroud)
2号房间由Alex(作为起居室)和林肯(作为餐厅)同时占用; 这不应该被允许.
更新2 …
我有兴趣以重构安全的方式在运行时检索局部变量(和参数)的名称.我有以下扩展方法:
public static string GetVariableName<T>(Expression<Func<T>> variableAccessExpression)
{
var memberExpression = variableAccessExpression.Body as MemberExpression;
return memberExpression.Member.Name;
}
Run Code Online (Sandbox Code Playgroud)
...返回通过lambda表达式捕获的变量的名称:
static void Main(string[] args)
{
Console.WriteLine(GetVariableName(() => args));
// Output: "args"
int num = 0;
Console.WriteLine(GetVariableName(() => num));
// Output: "num"
}
Run Code Online (Sandbox Code Playgroud)
但是,这只能起作用,因为C#编译器将在匿名函数中捕获的任何局部变量(和参数)提升为幕后编译器生成的类中的同名实例变量(每个Jon Skeet).如果不是这种情况,则转换为Bodyto MemberExpression会失败,因为MemberExpression代表字段或属性访问.
这个变量是促销记录的行为,还是一个实现细节可能会在框架的其他版本中发生变化?
注意:这个问题是我前一个关于参数验证的概括.
在实现一个用于线程安全的类时,我是否应该在其构造函数的末尾包含一个内存屏障,以确保在访问它们之前已完成任何内部结构的初始化?或者消费者有责任在将实例提供给其他线程之前插入内存屏障吗?
简化问题:
由于初始化和线程安全类的访问之间缺乏内存屏障,下面的代码中是否存在种族危险可能会导致错误行为?或者线程安全类本身是否应该防止这种情况?
ConcurrentQueue<int> queue = null;
Parallel.Invoke(
() => queue = new ConcurrentQueue<int>(),
() => queue?.Enqueue(5));
Run Code Online (Sandbox Code Playgroud)
请注意,程序可以接受任何内容,如果第二个委托在第一个委托之前执行,则会发生这种情况.(null条件运算符?.可以防止NullReferenceException这里.)然而,程序抛出一个IndexOutOfRangeException,多次入NullReferenceException队5,陷入无限循环,或者做任何由种族危险引起的其他奇怪事情都是不可接受的关于内部结构.
详细问题:
具体来说,假设我正在为队列实现一个简单的线程安全包装器.(我知道.NET已经提供了ConcurrentQueue<T>;这只是一个例子.)我可以写:
public class ThreadSafeQueue<T>
{
private readonly Queue<T> _queue;
public ThreadSafeQueue()
{
_queue = new Queue<T>();
// Thread.MemoryBarrier(); // Is this line required?
}
public void Enqueue(T item)
{
lock (_queue)
{
_queue.Enqueue(item);
}
}
public bool TryDequeue(out T item)
{
lock (_queue)
{
if (_queue.Count == …Run Code Online (Sandbox Code Playgroud) 假设我想在线程之间使用布尔状态标志来进行协作取消.(我意识到最好使用一个CancellationTokenSource;这不是这个问题的重点.)
private volatile bool _stopping;
public void Start()
{
var thread = new Thread(() =>
{
while (!_stopping)
{
// Do computation lasting around 10 seconds.
}
});
thread.Start();
}
public void Stop()
{
_stopping = true;
}
Run Code Online (Sandbox Code Playgroud)
问:如果我在另一个线程上调用Start()0s和Stop()3s,那么循环是否保证在当前迭代结束时在10s左右退出?
我见过的绝大多数消息来源表明上述内容应该按预期工作; 见: MSDN ; Jon Skeet ; 布赖恩吉迪恩 ; 马克格拉维尔 ; Remus Rusanu.
但是,volatile只会在读取时生成获取栅栏,并在写入时生成释放栅栏:
易失性读取具有"获取语义"; 也就是说,保证在指令序列之后发生的任何内存引用之前发生.易失性写入具有"释放语义"; 也就是说,保证在指令序列中的写指令之前的任何存储器引用之后发生.(C#规格)
因此,正如Joseph Albahari所观察到的那样,无法保证不会(似乎)交换易失性写入和易失性读取.因此,后台线程可能会在当前迭代结束后继续读取_stopping(即false)的陈旧值.具体地说,如果我Start()在0和Stop()3s …
据我所知,C#是一种安全的语言,除了通过unsafe关键字之外,不允许访问未分配的内存.但是,当线程之间存在不同步的访问时,其内存模型允许重新排序.这会导致竞争危险,在实例完全初始化之前,对新实例的引用似乎可用于竞赛线程,并且是双重检查锁定的众所周知的问题.Chris Brumme(来自CLR团队)在他们的Memory Model文章中解释了这一点:
考虑标准的双锁协议:
if (a == null)
{
lock(obj)
{
if (a == null)
a = new A();
}
}
Run Code Online (Sandbox Code Playgroud)
这是在典型情况下避免锁定读取'a'的常用技术.它在X86上运行得很好.但它将被ECMA CLI规范的合法但薄弱的实施所打破.确实,根据ECMA规范,获取锁具有获取语义并释放锁具有释放语义.
但是,我们必须假设在建造'a'期间已经发生了一系列商店.这些商店可以任意重新排序,包括将它们推迟到将新对象分配给'a'的出版商店之后的可能性.那时,在store.release之前有一个小窗口离开锁.在该窗口内,其他CPU可以在引用'a'中导航并查看部分构造的实例.
我一直对"部分构造的实例"的含义感到困惑.假设.NET运行时在分配而不是垃圾收集(讨论)时清除内存,这是否意味着另一个线程可能会读取仍包含垃圾收集对象数据的内存(如不安全语言中发生的情况)?
考虑以下具体示例:
byte[] buffer = new byte[2];
Parallel.Invoke(
() => buffer = new byte[4],
() => Console.WriteLine(BitConverter.ToString(buffer)));
Run Code Online (Sandbox Code Playgroud)
以上是竞争条件; 输出将是00-00或00-00-00-00.但是,第二个线程是否有可能在数组的内存初始化为0 buffer 之前读取新引用,并输出一些其他任意字符串?
从MSDN文档中的Array.Copy方法:
在多维数组之间进行复制时,数组的行为类似于长一维数组,其中行(或列)在概念上是端对端放置的.例如,如果一个数组有三行(或列),每行包含四个元素,则从数组开头复制六个元素将复制第一行(或列)的所有四个元素和第二行的前两个元素(或列).
我一直认为,在C#中,二维数组按行主要顺序排列(类似地用于更高维度),所以我对上述文档中带括号的"或列"的含义感到困惑.这是否意味着.NET Framework可能存在使用列主要排序的情况?
我正在按照MSDN的推荐IComparer<T>从Comparer<T>类中派生出一个实现.例如:
public class MyComparer : Comparer<MyClass>
{
private readonly Helper _helper;
public MyComparer(Helper helper)
{
if (helper == null)
throw new ArgumentNullException(nameof(helper));
_helper = helper;
}
public override int Compare(MyClass x, MyClass y)
{
// perform comparison using _helper
}
}
Run Code Online (Sandbox Code Playgroud)
然而,根据这一办法,在MyComparer类继承的Default,并Create从静态成员Comparer<T>类.这是不可取的,因为所述成员的实现与我的派生类无关,并且可能导致误导行为:
// calls MyClass.CompareTo or throws InvalidOperationException
MyComparer.Default.Compare(new MyClass(), new MyClass());
Run Code Online (Sandbox Code Playgroud)
由于所需的Helper参数,我的比较器不能有一个默认实例,也不能从a初始化它自己Comparison<T>,所以我不能用有意义的实现隐藏继承的静态成员.
这种情况的推荐做法是什么?我正在考虑三种选择:
IComparer<T>手动实现,而不是从中派生Comparer<T>,以避免继承所述静态成员
保留继承的静态成员,并假设消费者知道不使用它们
使用抛出的新实现隐藏继承的静态成员InvalidOperationException:
public …Run Code Online (Sandbox Code Playgroud)在Mono上运行计算密集型多处理代码时,我遇到了严重的性能问题.下面的简单片段使用蒙特卡罗方法估计pi的值,证明了这个问题.
该程序产生许多线程,这些线程等于当前机器上的逻辑核心数,并对每个线程执行相同的计算.当使用.NET Framework 4.5在Windows 7的Intel Core i7笔记本电脑上运行时,整个过程在4.2秒内运行,并且线程各自执行时间之间的相对标准偏差为2%.
但是,当使用Mono 2.10.9在同一台机器(和操作系统)上运行时,总执行时间最长可达18秒.各个线程的性能之间存在巨大差异,最快的完成时间仅为5.6秒,最慢的时间为18秒.平均值为14 s,相对标准偏差为28%.
原因似乎不是线程调度.将每个线程固定到不同的核心(通过调用BeginThreadAffinity和SetThreadAffinityMask)不会对线程的持续时间或差异产生任何显着影响.
类似地,在每个线程上多次运行计算(并单独计时)也会给出看似临时的持续时间.因此,问题似乎也不是由每个处理器的预热时间引起的.
我发现有所作为的是将所有8个线程固定到同一个处理器.在这种情况下,整体执行时间为25秒,这比在单个线程上执行8倍工作要慢1%.此外,相对标准偏差也降至1%以下.因此,问题不在于Mono的多线程本身,而在于它的多处理.
有没有人有解决方案如何解决这个性能问题?
static long limit = 1L << 26;
static long[] results;
static TimeSpan[] timesTaken;
internal static void Main(string[] args)
{
int processorCount = Environment.ProcessorCount;
Console.WriteLine("Thread count: " + processorCount);
Console.WriteLine("Number of points per thread: " + limit.ToString("N0"));
Thread[] threads = new Thread[processorCount];
results = new long[processorCount];
timesTaken = new TimeSpan[processorCount];
for (int i = 0; i < processorCount; ++i)
threads[i] = …Run Code Online (Sandbox Code Playgroud) 状态的MSDN文档Interlocked.Increment:
此方法通过包装来处理溢出条件:if location = Int32.MaxValue,location + 1 = Int32.MinValue.没有异常被抛出.
在这种情况下," location + 1"是什么意思?如果Increment改变位置字段旁边的内存位置,那么这可能不会导致.NET运行时损坏,因为这个相邻的位置可能是任何东西(对象引用,类元数据等)?
c# ×8
.net ×7
arrays ×1
icomparer ×1
interlocked ×1
javascript ×1
lambda ×1
mono ×1
overflow ×1
performance ×1
sql ×1
sql-server ×1
t-sql ×1
volatile ×1